c++ - 使用临时函数对象进行全局初始化

标签 c++ gcc c++11 clang

下面的代码

#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 的扩展/错误?

最佳答案

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:

cast-expression:

  • unary-expression
  • ( type-id ) cast-expression

由于一对空括号 () 不是一元表达式,因此该产生式不可用,编译器应从 5.2p1 中选择产生式:

postfix-expression:

  • [...]
  • postfix-expression ( expression-listopt )
  • [...]

其中 postfix-expression(std::random_device()) 并且省略了 expression-list

我已经提交了 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56239在 gcc bugzilla 上,看起来应该很快就会解决。

请注意,如果您向 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);

关于c++ - 使用临时函数对象进行全局初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14732132/

相关文章:

c++ - 为什么 C++11 允许二次初始化

c++ - 平行于向上 vector 转换阴影时的 LookAt 矩阵

C++ 连接两个数组而不进行深度复制

c++ - 第一次使用socket编程。连接没有发生。

c++ - 指向未知类函数的任意指针 - 类型转换无效

c++ - 如何在 GCC 回溯中获取非动态符号?

c - 伪终端不打印输出

c++ - Cygwin GCC 与 Visual Studio 库链接

c++ - std::regex 的正则表达式选项

C++ : how do I use type_traits to determine if a class is trivial?