强制转换操作符函数在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++, 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;

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'

英特尔c++编译器也拒绝此代码(参见现场演示在这里)

那么,问题是哪个编译器在这里?这里是g++不正确还是其他3个编译器不正确?

[basic.lookup.classref]/7:

如果id-expression转换函数id,则首先在对象表达式的类中查找其转换类型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并且引用不同时才会出现错误实体?

Erwin Unruh:目的是你在两种情况下都要看。如果你只找到一次,那就是标志。如果在两个符号中都找到它,则两个符号在某些方面必须是"相同的"。(如果你没有找到,这是一个错误)。

所以我想说Clang错了:从某种程度上说,Clang的意图是我们发现了T,即使只是在类中。

相关内容

最新更新