C ++ templated cast operator - conversion from non-scalar type

I am trying to understand how the translation operator works with templates.

Consider the following code:

#include <iostream> using namespace std; struct S { int v; }; class A { public: A(void* ptr) : ptr(ptr) {} void* ptr; template<typename T> const T& as() const { return *static_cast<T*>(ptr); } template<typename T> operator const T&() const { return as<T>(); } }; int main() { S test; test.v = 123; A a(&test); S s = a.as<S>(); S s2 = a; // error here const S& s3 = a; cout << sv << endl; cout << s2.v << endl; cout << s3.v << endl; return 0; } 

gcc gives me the following compilation error:

conversion from "A to non-scalar type" S requested

I know that I can fix the problem by adding another โ€œoperator T () const", but why the compiler can not determine the correct conversion in this case?

Oddly, clang doesn't complain and compiles just fine.

(tested with gcc4.7, gcc4.8 and clang3.2)

+4
source share
1 answer

This is because two transformations are required to initialize s2 with const S & ; one to convert the link to temporary, and one to copy the temporary into your variable. C ++ allows only one automatic conversion.

For example, this also works:

 S s2(a); 

Since you no longer need to create temporary ones.

Note that in this particular case, the standard has a paragraph. In C ++ 03 8.5p14:

Otherwise (i.e., for the remaining cases of copy initialization), user-defined conversion sequences that can be converted from a source type to a destination type or (when a conversion function is used) to its derived class are listed as described in 13.3.1.4, and the best selected using overload resolution (13.3). If the conversion cannot be performed or is ambiguous, the initialization is poorly formed. The selected function is called with an initializer expression as an argument; if the function is a constructor, the call initializes the temporary destination type. The result of the call (which is temporary for the constructor) is then used to directly initialize, according to the above rules, an object that is the copy initialization destination. In some implementation cases, it is allowed to exclude copying inherent in this direct initialization by creating an intermediate result directly in the initialized object; see 12.2, 12.8.

+6
source

Source: https://habr.com/ru/post/1502647/


All Articles