C ++转换运算符和重载决策

时间:2012-02-08 16:41:59

标签: c++ overload-resolution conversion-operator

鉴于此示例,其中包含一些重载:

#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;?任何人都可以引用涵盖此案例的标准的特定部分吗?

3 个答案:

答案 0 :(得分:4)

因为模板参数推导不采用用户定义的隐式 转化为帐户。结果就是当你写下:

test << source;

,编译器无法为第一个函数找到合适的T 模板;它试图找到T以使T const*具有相同的效果 输入您的T,这是不可能的。参数演绎失败,并且 没有将模板的实例化添加到重载集。以来 第二个参数中没有模板参数 功能模板,没有参数推断失败,以及 结果实例化成为重载集的唯一成员,并且 所以最终被选中了。

答案 1 :(得分:0)

它使用T隐式转换为wchar_t。任何类型都可以转换为void*,因此编译器会调用operator<<的那个版本。 T*运算符从未成为候选者,因为无法从T*隐式获取T。你的意思是让它成为T& <<运算符吗?

答案 2 :(得分:0)

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

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