使用指针参数在模板实例化之间进行选择

iam*_*ind 5 c++ compiler-construction templates

查看以下测试代码:

template<class T> struct Wrap {};

template<typename T> inline
void fun (T *&Int)          // **choice 1**
{}

template<typename T> inline
void fun (Wrap<T> *&Int)    // **choice 2**
{}

int main()
{
  int i = 6;
  fun((char*&)(i));         // **call 1**
  fun((Wrap<char>*&)(i));   // **call 2**
}
Run Code Online (Sandbox Code Playgroud)

当我在linux g ++中运行此代码时,它按预期工作.当使用char*&调用fun()时,它会直接调用选择1的函数.但是,当我们使用Wrap <char>*&调用fun()时,我感兴趣并且它调用了选项2.即使选择1和2都对第二次调用有效,编译器设法选择更好的竞争者 - >选择2 (因为它存在).

问题:是否保证,对于C++的任何其他编译器,将保留相同的行为?如果没有,那么还有其他选择让它具有确定性吗?

Pup*_*ppy 6

选择第二个选择因为它比第一个选择更专业,即T*&可以绑定到任何非临时选项T*,但Wrap<T>*&只能绑定到非临时选项Wrap<T>*.据我所知,这是标准的,应该是可移植的行为,但在实践中,当涉及到这类事物时,实际上是不可移植的,通常不是什么是标准的定义.

  • 它实际上是可移植的,但它们不是模板的特化,而是两个独立的模板,恰好是重载. (3认同)

Dav*_*eas 2

虽然代码可能看起来像模板专门化,但事实并非如此。该语言不允许部分模板函数专业化。这两个是不相关的模板,恰好是重载的。

编译器将使用通常的查找机制查找对的调用fun( (Wrap<char>*&) i ),将找到两个模板并确定存在两个潜在的重载:

template <typename T> void fun( T*& );      // with T == Wrap<char>
template <typename T> void fun( Wrap<T>*& ) // with T == char
Run Code Online (Sandbox Code Playgroud)

然后,重载解析将确定第二个是更好的匹配并将其实例化。这是由标准保证的,但要注意:它们不是相同的模板,而是不同的模板,您可能会遇到意外的结果。请参阅@LiKao 链接的文章以获取更多见解。