转换操作符函数在g ++中编译得很好,但在其他编译器中却没有.为什么?

Des*_*tor 10 c++ g++ visual-c++ language-lawyer clang++

考虑以下计划:

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 ?
}
Run Code Online (Sandbox Code Playgroud)

该程序在g ++中编译良好(请参阅此处的实时演示)

但它在clang ++,MSVC++和Intel C++编译器的编译中失败了

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;
Run Code Online (Sandbox Code Playgroud)

MSVC++给出以下错误(请参阅此处的实时演示)

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

英特尔C++编译器也拒绝此代码(请参阅此处的实时演示)

那么,问题是哪个编译器就在这里?这里g ++是不正确的还是其他3个编译器不正确?C++标准对此有何看法?

Col*_*mbo 8

[basic.lookup.classref]/7:

如果id-expressionconversion-function-id,则首先在对象表达式的类中查找conversion-type-id,并使用名称(如果找到).否则,它将在整个postfix-expression的上下文中查找 .在每个查找中,仅考虑表示其特化类型的类型或模板的名称.[ 例如:

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
}
Run Code Online (Sandbox Code Playgroud)

- 结束例子 ]

这表明该示例可能没问题,尽管在上面的示例中,A先前已声明为类型名称,可见main.

这在1999年提交的核心问题156中进行了讨论:

怎么样:

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?
}
Run Code Online (Sandbox Code Playgroud)

这种解释是否正确?或者只有T在两个范围中找到并引用不同的实体时才意味着这是一个错误?

Erwin Unruh:意图是你在两种情况下都看.如果你只发现一次,那就是符号.如果你在两者中找到它,那么两个符号在某些方面必须是"相同的".(如果你没找到它,那就是错误).

所以我说Clang是错的:在某种程度上,在措辞中表达的意图是我们发现T,即使只是在课堂上.

  • @Columbo:我不太了解standerdese.请问用简单的词语解释什么是id表达式? (2认同)
  • 知道这看起来很熟悉.[llvm bug 27807](https://llvm.org/bugs/show_bug.cgi?id=27807) (2认同)