我想创建一个constexpr函数,它返回系统的字节序,如下所示:
constexpr bool IsBigEndian()
{
constexpr int32_t one = 1;
return (reinterpret_cast<const int8_t&>(one) == 0);
}
现在,由于函数将在编译时而不是在实际的目标机器上执行,因此C ++规范给出了什么保证以确保返回正确的结果?
答案 0 :(得分:9)
无。事实上,该计划是不正确的。来自[expr.const]:
条件表达式e是核心常量表达式,除非e的评估遵循规则 抽象机器(1.9),将评估以下表达式之一:
- [...]
-reinterpret_cast
- [...]
并且,来自[dcl.constexpr]:
对于既没有默认也不是模板的
constexpr
函数或constexpr
构造函数,如果没有参数 存在这样的值,使得函数或构造函数的调用可以是被评估的子表达式 核心常量表达式(5.20),或者,对于构造函数,某个对象(3.6.2)的常量初始化器, 方案形象不健全;无需诊断。
这样做的方法是希望你的编译器足够好,可以为你的机器的字节序提供宏。例如,在gcc上,我可以使用__BYTE_ORDER__
:
constexpr bool IsBigEndian() {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
return false;
#else
return true;
#endif
}
答案 1 :(得分:2)
正如Barry所说,您的代码不是合法的C ++。但是,即使你带走了constexpr
部分,它仍然仍然不是合法的C ++。您的代码违反了严格的别名规则,因此代表了未定义的行为。
实际上,在C ++中没有办法在不调用未定义行为的情况下检测对象的字节序。将其转换为char*
并不起作用,因为标准不需要大或小的序列顺序。因此,虽然您可以通过一个字节读取数据,但您无法从该值合法地推断出任何内容。
通过union
输入惩罚失败,因为您根本不允许在C ++中通过union
输入双关语。即使你再次......,C ++也不会将实现限制为大或小端序。
因此,就C ++而言,无论是在编译时还是在运行时,都无法检测到它。