英特尔与海湾合作委员会在 constexpr 上
Intel vs GCC on constexpr
以下代码在 Intel-2015 中编译正常,但在 gcc 4.8.3 中失败谁是对的?
#include <iostream>
void f( int const& x ) { std::cout << x << std::endl; }
struct S
{
static constexpr int ce = 42;
};
int main()
{
f(S::ce);
return 0;
}
G++ 错误:
/tmp/ccOIxa2V.o: In function `main':
test_constexpr.cpp:(.text+0x36): undefined reference to `S::ce'
collect2: error: ld returned 1 exit status
因为函数f
接受引用参数,所以必须有一个引用可以在运行时指向的S::ce
定义;编译器不能只用文字 42 替换参数。 因此,您必须添加一个类外定义:
const int S::ce;
就像使用非constexpr
变量一样。 这会在运行时为值分配一个内存位置,供引用和其他在编译时无法计算的内容使用。
有关更多信息,请参阅此 GCC 错误报告(其中有注释解释为什么它实际上不是错误)。
我认为GCC是对的。顺便说一句,CLang 3.5.1 给出了同样的错误。
问题是,只有当常量静态变量的地址未被占用并且它们未绑定到引用时,才允许不定义常量静态变量。
您的示例将引用限定为该引用,因此需要显式定义。
从 C++11 草案 (9.4.2.3),方便编辑:
文本类型的静态数据成员可以使用 constexpr 说明符在类定义中声明;[...]如果在程序中使用 odr 使用 (3.2) 的成员,则仍应在命名空间作用域中定义该成员 [...]。
在 3.2 中:
名称显示为潜在求值表达式的变量 [...] 被 odr 使用,除非它是一个满足出现在常量表达式 (5.19) 中的要求的对象,并且立即应用左值到右值的转换 (4.1)。
粗略地说,每次使用变量时都会完成左值到右值转换的东西,除非在绑定引用或作为参数到一元获取地址运算符&
时。
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 多成员Constexpr结构初始化
- 条件constexpr函数
- constexpr 函数中的非文字(通过 std::is_constant_evaluated)
- Visual C++ constexpr Hints
- 如何确认我的constexpr表达式实际上已经在编译时执行
- 为什么constexpr的性能比正常表达式差
- 是否可以使用if constexpr删除控制流语句
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 为什么std::isnan 不是 constexpr?
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 更多constexpr容器是否需要mark_immutable_if_consexpr
- C++从其他 constexpr 创建 lambda 不能按顺序执行 Constexpr
- constexpr上下文中std::initializer_list的验证
- constexpr构造函数需要常量成员函数时出现问题
- vs 2015 constexpr变量不恒定,但与2019相比还好吗
- C++constexpr实现差异
- 海湾合作委员会和Clang在lambda的constexpr-ness上存在分歧?
- 英特尔与海湾合作委员会在 constexpr 上