【问题标题】:cast operator function compiles fine in g++ but not in other compilers. Why? [duplicate]cast 运算符函数在 g++ 中编译得很好,但在其他编译器中却不行。为什么? [复制]
【发布时间】:2017-04-01 05:00:14
【问题描述】:

考虑以下程序:

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++ 和 Intel 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++ 标准对此有何规定?

【问题讨论】:

  • 哇,非常好的问题!

标签: c++ visual-c++ g++ language-lawyer clang++


【解决方案1】:

[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 可见。

这在core issue 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 是错误的:在某种程度上,用措辞表达的意图是我们找到 T,即使只是在课堂上。

【讨论】:

  • 一个令人惊讶的问题!
  • 你也应该说ICC和MSVC++也是错的。只有 g++ 是对的!!!
  • @Columbo:我不太了解标准。请您用更简单的语言解释一下什么是 id 表达式?
  • @Destructor 表示实体的表达式(更通俗地说,是实体的“名称”)。
  • 知道这看起来很眼熟。 llvm bug 27807
猜你喜欢
  • 2016-01-21
  • 1970-01-01
  • 2015-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多