鉴于此示例,其中包含一些重载:
#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;
?任何人都可以引用涵盖此案例的标准的特定部分吗?
答案 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*
。因此,可以使用这些参数调用此函数并使用它,因为无法推导出另一个函数。