Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

User-defined conversion operator template and built-in operators: no match for operator

Consider the following MCVE.

#include <type_traits>

struct A {
    template<typename T, typename std::enable_if<std::is_same<T,int>::value,int>::type = 0>
    operator T() const { return static_cast<T>(1); }
};

int main() {
    int x = 1;
    A a;
    return x + a;
}

clang compiles it fine. DEMO

But GCC fails with:

error: no match for 'operator+' (operand types are 'int' and 'A')
  return x + a;
         ~~^~~

Question: who is right and why?

like image 463
rustyx Avatar asked Apr 04 '18 14:04

rustyx


People also ask

What is user-defined conversion in c++?

User-defined conversions allow you to specify object conversions that are implicitly applied by the compiler, in addition to standard built-in type conversions.

What is user-defined conversion?

For more information, see Standard Conversions. User-defined conversions perform conversions between user-defined types, or between user-defined types and built-in types. You can implement them as Conversion constructors or as Conversion functions.

How many types are there in user-defined conversion?

There are two types of user-defined conversions: Conversion constructors and conversion functions.

Which of the following is the correct syntax of the conversion function?

Explanation: The syntax of operator conversion is operator float()const.


1 Answers

I believe clang is right.

To do lookup on +, since at least one argument has class type, we consider member, non-member, and builtin candidates. There aren't any member or non-member candidates, so that's eay enough. There is a builtin candidate for int operator+(int, int), which is the only candidate. That candidate is viable because A can be convertible to int, directly (we have a standard conversion from A to const A& for the implicit object parameter, and then the user defined conversion from that to int, there's no further conversion necessary). As we have one viable candidate, that trivially makes it the best viable candidate.


Note that if A just had operator int() const { return 1; }, gcc would accept it. It's just the conversion function template that fails to be considered.

like image 113
Barry Avatar answered Sep 30 '22 12:09

Barry