简体   繁体   English

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

[英]C++ conversion operator and overload resolution

Given this example, which includes a few overloads: 鉴于此示例,其中包含一些重载:

#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;
}


And its output: 它的输出:

1
Conversion
1
Conversion
2


My question is - why is void operator <<(A<T> &, const void *) being called for the statement test << source; 我的问题是 - 为什么要为语句test << source;调用void operator <<(A<T> &, const void *) test << source; ? Can anyone cite a specific part of the standard that covers this case? 任何人都可以引用涵盖此案例的标准的特定部分吗?

Because template argument deduction doesn't take user defined implicit conversions into account. 因为模板参数推导不会考虑用户定义的隐式转换。 The result is that when you wrote: 结果就是当你写道:

test << source;

, the compiler could not find a suitable T for the first function template; ,编译器无法为第一个函数模板找到合适的T ; it is trying to find a T such that T const* has the same type as your T , which isn't possible. 它试图找到一个T ,使得T const*与你的T具有相同的类型,这是不可能的。 Argument deduction fails, and no instantiation of the template is added to the overload set. 参数推断失败,并且没有将模板的实例化添加到重载集。 Since there's no template argument in the second parameter of the second function template, there's no argument deduction to fail, and the resulting instantiation becomes the only member of the overload set, and so ends up being chosen. 由于第二个函数模板的第二个参数中没有模板参数,因此没有参数推断失败,并且生成的实例化成为重载集的唯一成员,因此最终被选中。

It uses T 's implicit conversion to wchar_t . 它使用T的隐式转换为wchar_t Any type is convertible to void* so the compiler calls that version of the operator<< . 任何类型都可以转换为void*因此编译器会调用该operator<<版本。 The T* operator was never a candidate because there was no way to get a T* implicitly from a T . T*运算符从来都不是候选者,因为无法从T隐式获得T* did you mean to make it a T& << operator? 你的意思是让它成为T& <<运营商吗?

Implicit deduction of template arguments will not consider user defined implicit conversions. 模板参数的隐式推导不会考虑用户定义的隐式转换。 As such calling template <class T> void operator <<(A<T> &, const T *) would deduce T to be wchar_t from the first argument, but the second argument is T instead of const wchar_t* . 因此,调用template <class T> void operator <<(A<T> &, const T *)会将T从第一个参数推导为wchar_t ,但第二个参数是T而不是const wchar_t* Therefore the compiler will fail to match that operator. 因此编译器将无法匹配该运算符。

For template <class T> void operator <<(A<T> &, const void *) the matter looks different: T will be deduced to be wchar_t from the first function argument. 对于template <class T> void operator <<(A<T> &, const void *) ,问题看起来不同: T将从第一个函数参数推断为wchar_t The second argument can be implicitly converted to const wchar_t* by a user defined conversion, which can then be implicitly cast to a const void* by a build in conversion. 第二个参数可以通过用户定义的转换隐式转换为const wchar_t* ,然后可以通过转换构建将其隐式转换为const void* Therefore this function is callable with those arguments and is used, since the other one couldn't be deduced. 因此,此函数可以使用这些参数调用并使用,因为无法推导出另一个函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM