我可以reinterpret_cast constexpr函数的参数吗? [英] Can I reinterpret_cast the parameter of a constexpr function?
问题描述
我想编写一个在编译时求值的函数,它需要一个指向4字节数组的指针,并输出一个与该数组具有相同位模式的int。
所以我想出了:
I want to write a function evaluated at compile time, it takes a pointer to 4 bytes array, and outputs an int that has the same bit pattern as that array. So I came up with:
constexpr int f(const char* p) {
return *reinterpret_cast<int*>(p);
}
然后,我想使用 f()
像这样:
Then, I want to use f()
like this:
switch(x) {
case f("GOOG"):
// do something
case f("MSFT"):
// do something
case f("NIKE"):
// do something
}
但是,我遇到了编译器错误:
However, I got a compiler error:
error: accessing value of ‘"GOOG"’ through a ‘int’ glvalue in a constant expression case f("GOOG")
- 如何修复
f()
以便编译? - 是否有更好的方法来实现相同的目标?
- How to fix
f()
so it compiles? - Is there a better way to accomplish the same goal?
推荐答案
恭喜,您已经激活了严格的别名陷阱卡,并且代码具有未定义的行为(如果可以编译的话)
Congratulations, you have activated the strict aliasing trap card and your code has undefined behaviour (if it would compile).
您的代码中几乎没有错误,正确代码版本是:
There are few errors in your code, the "correct" version is:
constexpr int f(const char* p) {
return *reinterpret_cast<const int*>(p);
}
-
reinterpret_cast
无法丢弃const
。 -
cursor-> p
错字? reinterpret_cast
cannot cast awayconst
.cursor->p
typo?
但是由于 const char *
不会指向 int
强制转换为严格的别名规则。 int
不是可以别名的类型之一,只有 std :: byte,(无符号)char
可以。
But since const char*
does not point to an int
, casting to it breaks the strict aliasing rule. int
is not one of the types that can alias others - only std::byte, (unsigned) char
can.
最干净的是:
#include <cstring>
constexpr int f(const char* p) {
int val = 0;
static_assert(sizeof(val)==4); // If the array is 4-byte long.
std::memcpy(&val,p,sizeof val);
return val;
}
但是 std :: memcpy
不是 constexpr
,即使在运行时这也可能没有任何开销,编译器可以识别出这一点并自行重新解释字节。
But std::memcpy
is not constexpr
, even at run-time this will probably not have any overhead, compiler can recognize this and reinterpret the bytes on its own.
所以要进行位移:
constexpr int f(const char* p) {
int value=0;
using T = decltype (value);
for(std::size_t i =0; i< sizeof(T);++i)
value|= (T)p[i] << (8*i);
return value;
}
int main(){
// @ == 64
// 1077952576 = 01000000 01000000 01000000 01000000
static_assert(f("@@@@") ==1077952576);
}
只要是学究的 @@@@ code>的长度为5,而不是4。
Just to be pedantic "@@@@"
has length 5, not 4.
这篇关于我可以reinterpret_cast constexpr函数的参数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!