简体   繁体   中英

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; ? 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; it is trying to find a T such that T const* has the same type as your T , which isn't possible. 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 . Any type is convertible to void* so the compiler calls that version of the operator<< . The T* operator was never a candidate because there was no way to get a T* implicitly from a T . did you mean to make it a T& << operator?

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* . 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. 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. Therefore this function is callable with those arguments and is used, since the other one couldn't be deduced.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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