程序在3个主要的C ++编译器中被编译得不同。 哪一个是对的?

作为一个有趣的后续(虽然没有很大的实际重要性)到我以前的问题: 为什么C ++允许我们在声明variables时在括号中包围variables名?

我发现将括号中的声明与注入的类名称function组合在一起可能会导致令人惊讶的编译器行为结果。

看看下面的程序:

#include <iostream> struct B { }; struct C { C (){ std::cout << "C" << '\n'; } C (B *) { std::cout << "C (B *)" << '\n';} }; B *y = nullptr; int main() { C::C (y); } 
  1. 用g ++编译4.9.2给了我下面的编译错误:

     main.cpp:16:10: error: cannot call constructor 'C::C' directly [-fpermissive] 
  2. 它使用MSVC2013 / 2015成功编译并打印C (B *)

  3. 它与叮当3.5编译成功,并打印C

所以强制性的问题是哪一个是对的? 🙂

(我强烈地向铿锵的版本,而msvc的方式来停止声明variables后,只是改变types与技术上它的typedef似乎有点奇怪)

GCC是正确的,至less根据C ++ 11的查找规则。 3.4.3.1 [class.qual] / 2指定如果嵌套名称说明符与类名称相同,则表示构造函数不是注入的类名称。 举例说明:

 B::A ba; // object of type A A::A a; // error, A::A is not a type name struct A::A a2; // object of type A 

它看起来像MSVC曲解它作为函数风格的转换expression式创build一个临时Cy作为构造函数参数; 而Clang把它误解为一个叫做C的variables的声明。

G ++是正确的,因为它提供了一个错误。 因为构造函数不能以没有new运算符的格式直接调用。 虽然你的代码调用C::C ,但它看起来像一个构造函数调用。 但是,根据C ++ 11标准3.4.3.1,这不是一个合法的函数调用,也不是一个types名称( 见Mike Seymour的答案 )。

铛是错误的,因为它甚至没有调用正确的function。

MSVC是合理的,但仍然不符合标准。