Clang не может найти оператор преобразования - PullRequest
5 голосов
/ 31 марта 2020

В следующем коде clang жалуется, что не существует оператора преобразования:

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;
};

Это происходит со всеми версиями clang 6-9, см. https://godbolt.org/z/ELuRHp. Сообщение об ошибке выглядит следующим образом:

<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))){
                  ^~~~~~~~~~~~~~~~

Тот же код компилируется с g cc 7-9 просто отлично, поэтому мне интересно, если это ошибка в Clang или, возможно, код не является правильным .

Редактировать: более короткую версию той же ошибки, которая была предоставлена ​​@ daniel-langr, можно найти здесь https://godbolt.org/z/Krnh27. Исходный пример кода - это упрощенная версия класса в нашей кодовой базе, отсюда и ненужный decltype.

1 Ответ

0 голосов
/ 31 марта 2020

Это похоже на ошибку лягушки.

Из поиска без определения имени :

Для имени, используемого в любом месте определения класса (включая спецификаторы базового класса и определения вложенного класса), за исключением внутри тела функции-члена, аргумента по умолчанию для функции-члена, спецификации исключения для функции-члена или инициализатора члена по умолчанию, где член может принадлежать к вложенному классу, определение которого является в теле включающего класса ищутся следующие области:

a) тело класса, в котором имя используется до момента использования

...

В соответствии с вышеизложенным ваша пользовательская функция преобразования должна быть видимой в конце типа возврата.

Вот еще один пример функция-член, которая отлично работает на g cc, но не компилируется на clang.

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