Clang Cannot Find Conversion Operator

Viewed 171

In the following code clang complains that there exist no conversion operator:

class A{
public:
  operator int () const {return i;}

  A(int i_): i(i_) {}

  template<class B>
  friend auto operator * (const B& l, A&& r)
  -> decltype(l * int(std::move(r))){
    return l * int(std::move(r));
  }

  int i;
};

This happens with all clang versions 6-9, see https://godbolt.org/z/ELuRHp. The error message is as follows:

<source>:11:19: error: cannot convert 'typename std::remove_reference<A &>::type' (aka 'A') to
'int' without a conversion operator
  -> decltype(l * int(std::move(r))){
                  ^~~~~~~~~~~~~~~~

The same code compiles with gcc 7-9 just fine, so I'm wondering if this is a bug in clang or maybe the code is not correct.

Edit: A shorter version of the same error, which was provided by @daniel-langr, can be found here https://godbolt.org/z/Krnh27. The original code example is a simplified version of a class in our code base, hence the unnecessary decltype.

1 Answers

This looks like a clang bug.

From unqualified name lookup:

For a name used anywhere in class definition (including base class specifiers and nested class definitions), except inside a member function body, a default argument of a member function, exception specification of a member function, or default member initializer, where the member may belong to a nested class whose definition is in the body of the enclosing class, the following scopes are searched:

a) the body of the class in which the name is used until the point of use

...

According to the above, your user-defined conversion function must be visible in the trailing return type.

Here is another example of a member function which works fine on gcc but does not compile on clang.

void f(A a, decltype(int(A)) {}
Related