Подтвердить что ты не робот

Функция оператора оператора компилируется в g++, но не в других компиляторах. Зачем?

Рассмотрим следующую программу:

struct S {
    using T = float;
    operator T() { return 9.9f; }
};
int main() {
    S m;
    S::T t = m;
    t = m.operator T(); // Is this correct ?
}

Программа компилируется в g++ (см. живое демо здесь)

Но это не удается в компиляции в clang++, MSVС++ и компиляторе Intel С++

clang++ дает следующие ошибки (см. живое демо здесь)

main.cpp:8:20: error: unknown type name 'T'; did you mean 'S::T'?
    t = m.operator T(); // Is this correct ?
                   ^
                   S::T
main.cpp:2:11: note: 'S::T' declared here
    using T = float;

MSVС++ дает следующие ошибки (см. живое демо здесь)

source_file.cpp(8): error C2833: 'operator T' is not a recognized operator or type
source_file.cpp(8): error C2059: syntax error: 'newline'

Компилятор Intel С++ также отклоняет этот код (см. живое демо здесь)

Итак, вопрос в том, какой компилятор здесь? Неверный здесь g++ или другие 3 компилятора здесь неверны? Что говорит об этом в стандарте С++?

4b9b3361

Ответ 1

[basic.lookup.classref]/7:

Если id-выражение является идентификатором функции-преобразования, , его идентификатор типа преобразования сначала просматривается в классе выражения объекта, а имя, если найдено, используется. В противном случае он рассматривается в контексте всего постфикс-выражение. В каждом из этих поисков рассматриваются только имена, которые обозначают типы или шаблоны, специализации которых являются типами. [Пример:

struct A { };
namespace N {
  struct A {
    void g() { }
    template <class T> operator T();
  };
}

int main() {
  N::A a;
  a.operator A();  // calls N::A::operator N::A
}

- конец примера]

Это означает, что пример может быть точным, хотя в приведенном выше примере A ранее был объявлен как имя типа, видимое для main.

Это обсуждалось в основной проблеме 156, поданной полностью в 1999 году:

Как насчет:

struct A { typedef int T; operator T(); };
struct B : A { operator T(); } b;
void foo() {
  b.A::operator T(); // 2) error T is not found in the context
                     // of the postfix-expression?
}

Правильно ли эта интерпретация? Или было намерением, что это будет ошибка только в том случае, если T было найдено в обеих областях и указано на разные объекты?

Эрвин Унру: Цель заключалась в том, что вы смотрите в обоих контекстах. Если вы найдете его только один раз, этот символ. Если вы найдете его в обоих, оба символа должны быть "одинаковыми" в некотором отношении. (Если вы не нашли его, его ошибка).

Итак, я бы сказал, что Clang ошибочен: намерение, выраженное в некоторой формулировке, заключается в том, что мы находим T, даже если только в классе.