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

时间:2016-11-17 15:14:33

标签: c++ visual-c++ g++ 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 ?
}

该程序在g ++中编译得很好(参见实时演示here

但它在clang ++,MSVC ++&英特尔C ++编译器

clang ++给出了以下错误(请参阅实时演示here

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 ++提供以下错误(请参阅实时演示here

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 ++编译器也拒绝此代码(请参阅实时演示here

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

1 个答案:

答案 0 :(得分:8)

[basic.lookup.classref]/7

  

如果 id-expression conversion-function-id ,首先会查找 conversion-type-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可见。

这在1999年提交的core issue 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?
}
     

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

     

Erwin Unruh:意图是你在两种情况下都看。如果您只找到一次,那就是符号。如果您在两者中都找到它,则两个符号在某些方面必须“相同”。 (如果你没有找到它,那就是错误)。

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