微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C模板选择

给出以下代码
#include <memory>
#include <iostream>

using namespace std;

template<typename T>
void test(T & value) {
  cout << "most generic" << endl;
}

template<typename T>
void test(shared_ptr<T> & value) {
  cout << "shared_ptr" << endl;
}

class A {};

int main(int argc,char ** argv) {
  A a;
  shared_ptr<A> p(new A());
  test(a);
  test(p);
  return 0;
}

为什么是电话

test(p)

用T = A实例化第二种形式的测试,而不是抱怨它不能区分两个签名?

解决方法

因为即使它们都是可重复解决的可行选择,所以第二个功能模板比第一个更加专业化.

根据C11标准第13.3.3 / 1段:

[…] Given these deFinitions,a viable function F1 is defined to be a better function than another viable function
F2 if for all arguments i,ICSi(F1) is not a worse conversion sequence than ICSi(F2),and then

— for some argument j,ICSj(F1) is a better conversion sequence than ICSj(F2),or,if not that,

— the context is an initialization by user-defined conversion (see 8.5,13.3.1.5,and 13.3.1.6) and the
standard conversion sequence from the return type of F1 to the destination type (i.e.,the type of the
entity being initialized) is a better conversion sequence than the standard conversion sequence from
the return type of F2 to the destination type. […] or,

— F1 is a non-template function and F2 is a function template specialization,

— F1 and F2 are function template specializations,and the function template for F1 is more specialized
than the template for F2
according to the partial ordering rules described in 14.5.6.2.

§14.5.6.2然后说明如何确定功能模板比另一个功能模板更专业化.特别是,根据14.5.6.2/2:

Partial ordering selects which of two function templates is more specialized than the other by transforming
each template in turn (see next paragraph) and performing template argument deduction using the function
type. The deduction process determines whether one of the templates is more specialized than the other. If
so,the more specialized template is the one chosen by the partial ordering process.

标准中的正式定义可能非常难以破译,但是它们的复杂性通常意味着明确地使语言的行为与大多数情况下我们预期的一样.

我们可以提供的关于您提供的重载的直观预期是接受std :: shared_ptr< T>当参数的类型为std :: shared_ptr< int>,因为它似乎是处理std :: shared_ptr<>因此,它看起来像一个比无约束的超载更好(更专业化)的候选人.

将这种直观的期望转化为明确的规则集的正式程序可能听起来很复杂,但是在我们的情况下,并不特别困难,我们想确定这是否超载:

template<typename T>
void f(std::shared_ptr<T>);

比这更专业:

template<typename U>
void f(U);

尽管在这种情况下,我们很容易根据我们的直觉来判断哪一种更加专业化,但是编译器必须依赖于一种算法,而且该算法必须在所有情况下工作.

在这种情况下,机制将如下:

>取第一个重载,将其模板参数T替换为类型参数(任何类型参数),例如int,并实例化相应的签名 – 函数参数将具有类型std :: shared_ptr< int>;
>通过提供该类型的对象(在这种情况下为shared_ptr< int>)作为其输入,总是可以调用第二个重载,并从中推导出类型U?
那么答案是的. U将被推断为std :: shared_ptr< int&gt ;;
>另一种方式现在:取第二个重载,将其模板参数U替换为任何类型参数,例如bool,并实例化相应的签名 – 函数参数将具有类型bool;
>它总是可以通过提供该类型的对象(bool)作为参数来调用一个重载,并从中推导出类型T?
>这里的答案当然不是.没有办法推断T,使得std :: shared_ptr< T>会匹配bool;
>结论:第一次超载比第二次更专业化.

当然,当有多个模板参数和多个函数参数时,事情变得稍微复杂一点,但是机制几乎相同.

原文地址:https://www.jb51.cc/c/111532.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐