以下代码
#include <random>
std::mt19937 generator((std::random_device())());
使用clang编译文件:
$ clang++ -c -std=c++0x test.cpp
但是使用gcc失败了:
$ g++ -c -std=c++0x test.cpp
test.cpp:3:47: erro: expected primary-expression before ‘)’ token
该代码在C ++ 11中有效吗?这是GCC中的错误还是Clang的扩展错误?
答案 0 :(得分:6)
gcc正在将子表达式(std::random_device())()
解析为函数类型std::random_device()
的强制转换。它有助于查看icc的错误输出,这比gcc的信息略多:
source.cpp(6): error: cast to type "std::random_device ()" is not allowed
std::mt19937 generator((std::random_device())());
^
source.cpp(6): error: expected an expression
std::mt19937 generator((std::random_device())());
^
相关产量为5.4p2:
铸表达:
- 一元表达式
- ( type-id ) cast-expression
由于一对空括号()
不是一元表达式,因此该生产不可用,编译器应从5.2p1中选择生产:
后缀表达式:
- [...]
- postfix-expression ( expression-list opt )
- [...]
其中后缀表达式为(std::random_device())
且表达式列表被省略。
我已经在gcc bugzilla上提交了http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56239,看起来应该很快就会解决。
请注意,如果要向operator()
提供参数,那么8.2p2需要编译器将表达式解析为强制转换,即使转换为函数类型是非法的(如果有多个参数) ,使用逗号运算符将参数列表解析为表达式:
(std::less<int>())(1, 2);
^~~~~~~~~~~~~~~~~~ illegal C-style cast
^~~~~~~~~~~~~~~~ type-id of function type std::less<int>()
^~~~~~ argument of C-style cast
^ comma operator
写这个的正确方法(除了使用C ++ 11通用初始化器语法之外)是添加另一层括号,因为 type-id 不能包含外括号:
((std::less<int>()))(1, 2);
答案 1 :(得分:2)
似乎GCC处理函数声明的方式存在问题。举个例子:
struct A
{
bool operator () () { return true; }
};
struct B
{
B(bool) { }
};
B b(( // This cannot be parsed as a function declaration,
A()() // and yet GCC 4.7.2 interprets it as such:
)); // "error: 'type name' declared as function returning
// a function B b((A()()));"
int main() { }
由于A()()
周围存在额外的括号,因此无法将语法形式B b(( A()() ));
解析为函数声明。
您问题示例中的声明略有不同:
B b(
(A())()
);
即使在这种情况下,(A())()
也不能被解释为返回返回A
的函数的函数类型(总是试图将b
视为函数带有未命名参数的声明)。所以问题是:它可以解释为其他什么吗?如果是这样,并且如果它在此上下文中有意义,那么编译器应该考虑将整个表达式解析为对象b
的构造。
这可能是GCC和Clang不同意的基本点:
int main()
{
(A())(); // OK for Clang, ERROR for GCC
}
我没有看到上述内容如何被解释为除了尝试构造类型为A
的临时函数并调用其调用运算符之外的其他内容。它不能是函数声明,因为如果将A
解释为返回类型,则缺少名称(反之亦然)。
另一方面,(A())
是用于创建类型A
的临时表的有效表达式,并且该临时表示支持调用运算符(其返回类型与{{{0}接受的类型相同) 1}}的构造函数)。因此,B
应该是(A())()
类型的有效表达式。
由于这个原因,我认为GCC的解析是错误的。