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

1

11

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?

Splat answered 4/4, 2018 at 14:1 Comment(0)
P
6

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.

Pomatum answered 4/4, 2018 at 17:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.