函数模板的优先级是否低于相同解析类型的函数?



这与我之前的问题密切相关,但我认为它足够明显,值得另发一篇文章。

这是我所引用的歧义的一种相当纯粹的形式:

template<typename T>
class Class {
public:
Class() = default;
template<typename U>
Class(Class<U> &) {}
};

这个类有两个可能冲突的构造函数:隐式复制构造函数和重绑定构造函数模板。看下面的例子:

Class<int> foo{};
Class<int> bar{foo};

在这种情况下,重绑定构造函数模板的解析类型将是Class<int>(Class<int> &)——与隐式复制构造函数相同的签名!

c++标准是否指定哪个构造函数具有优先级,或者它是实现定义的?

作为补充,在这些场景中,特殊成员函数(如复制构造函数)是否得到特殊处理?也就是说,场景

template<typename T>
class Vector {
public:
T x, y;
Vector foo(Vector &other) {
...
}
template<typename U>
Vector foo(Vector<U> &other) {
...
}
};
...
Vector<int> vec1{1, 2};
Vector<int> vec2{3, 4};
auto fooVec = vec1.foo(vec2);

的行为与第一个例子不同吗?

当你有一个模板专门化和一个常规函数时,如果其他条件相同(签名相同),常规函数被认为比专门化更好。这在[over.match.best.general]/2

中包含。

给定这些定义,一个可行函数f1被定义为比另一个可行函数f2更好的函数,如果对于所有参数i, ICS i (f1)不是比ICS i (f2)更差的转换序列,则

  • […]
  • F1不是函数模板专门化,F2是函数模板专门化,或者,如果不是,

这意味着在第一种情况下,不会使用默认的编译器生成的复制构造函数。原因是默认签名为Class(Class<int> const &),而模板将专门化为Class(Class<int>&)。因为它不需要做const限定,所以它是一个更好的匹配。

第二个示例将使用非模板版本,因为两个调用都将解析为Vector<int> foo(Vector<int> &),并且由于它们匹配,因此使用非模板版本。

最新更新