3

给定这个例子,其中包括一些重载:

#include <iostream>

class T
{
   public:
      operator const wchar_t *(void) const
      {
         std::cout << "Conversion" << std::endl;
         return L"Testing";
      }
};

template <class Elem>
class A
{
};

template <class T>
void operator <<(A<T> &, const T *)
{
   std::cout << "1" << std::endl;
}

template <class T>
void operator <<(A<T> &, const void *)
{
   std::cout << "2" << std::endl;
}

int main(void)
{
   A<wchar_t> test;
   T          source;

   test << L"1";
   test << static_cast<const wchar_t *>(source);
   test << source;
}


及其输出:

1
Conversion
1
Conversion
2


我的问题是 - 为什么void operator <<(A<T> &, const void *)要求发表声明test << source;?任何人都可以引用涵盖此案例的标准的特定部分吗?

4

3 回答 3

4

因为模板参数推导不考虑用户定义的隐式转换。结果是当你写的时候:

test << source;

,编译器找不到适合T第一个函数的模板;它正在尝试找到与您的类型相同的T此类,这是不可能的。参数推导失败,并且没有将模板的实例化添加到重载集中。由于第二个函数模板的第二个参数中没有模板参数,因此没有参数推导失败,并且生成的实例化成为重载集的唯一成员,因此最终被选中。T const*T

于 2012-02-08T17:02:10.903 回答
0

模板参数的隐式推导不会考虑用户定义的隐式转换。因此,调用template <class T> void operator <<(A<T> &, const T *)将推断Twchar_t来自第一个参数,但第二个参数是T而不是const wchar_t*. 因此编译器将无法匹配该运算符。

因为template <class T> void operator <<(A<T> &, const void *)事情看起来不同:T将推导出来是wchar_t从第一个函数参数。第二个参数可以const wchar_t*通过用户定义的转换隐式转换为,然后可以const void*通过内置转换隐式转换为 a。因此,该函数可以使用这些参数调用并使用,因为无法推断出另一个。

于 2012-02-08T16:54:41.563 回答
0

它使用T' 的隐式转换为wchar_t. 任何类型都可以转换为,void*因此编译器调用该版本的operator<<. 操作员从来都不是候选人,T*因为没有办法从 a中T*隐式地得到 a T。你的意思是让它成为一个T& <<运营商?

于 2012-02-08T16:45:11.490 回答