我可以 reinterpret_cast constexpr 函数的参数吗?
Can I reinterpret_cast the parameter of a constexpr function?
我想编写一个在编译时计算的函数,它接受一个指向 4 字节数组的指针,并输出一个与该数组具有相同位模式的 int。
所以我想出了:
constexpr int f(const char* p) {
return *reinterpret_cast<int*>(p);
}
然后,我想这样使用f()
:
switch(x) {
case f("GOOG"):
// do something
case f("MSFT"):
// do something
case f("NIKE"):
// do something
}
但是,我遇到了一个编译器错误:
error: accessing value of ‘"GOOG"’ through a ‘int’ glvalue in a constant expression case f("GOOG")
- 如何修复
f()
以便编译?
- 是否有更好的方法来实现相同的目标?
恭喜,您已经激活了严格的别名陷阱卡并且您的代码具有未定义的行为(如果它可以编译)。
您的代码中几乎没有错误,“正确”版本是:
constexpr int f(const char* p) {
return *reinterpret_cast<const int*>(p);
}
reinterpret_cast
无法丢弃const
.
cursor->p
打字错误?
但是由于 const char*
不指向 int
,转换为它打破了严格的别名规则。 int
不是可以为其他类型起别名的类型之一 - 只有 std::byte, (unsigned) char
可以。
最干净的是:
#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
,即使在 run-time 这可能不会有任何开销,编译器可以识别这一点并自行重新解释字节。
所以选择 bit-shifting:
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);
}
学究气 "@@@@"
的长度是 5,不是 4。
我想编写一个在编译时计算的函数,它接受一个指向 4 字节数组的指针,并输出一个与该数组具有相同位模式的 int。 所以我想出了:
constexpr int f(const char* p) {
return *reinterpret_cast<int*>(p);
}
然后,我想这样使用f()
:
switch(x) {
case f("GOOG"):
// do something
case f("MSFT"):
// do something
case f("NIKE"):
// do something
}
但是,我遇到了一个编译器错误:
error: accessing value of ‘"GOOG"’ through a ‘int’ glvalue in a constant expression case f("GOOG")
- 如何修复
f()
以便编译? - 是否有更好的方法来实现相同的目标?
恭喜,您已经激活了严格的别名陷阱卡并且您的代码具有未定义的行为(如果它可以编译)。
您的代码中几乎没有错误,“正确”版本是:
constexpr int f(const char* p) {
return *reinterpret_cast<const int*>(p);
}
reinterpret_cast
无法丢弃const
.cursor->p
打字错误?
但是由于 const char*
不指向 int
,转换为它打破了严格的别名规则。 int
不是可以为其他类型起别名的类型之一 - 只有 std::byte, (unsigned) char
可以。
最干净的是:
#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
,即使在 run-time 这可能不会有任何开销,编译器可以识别这一点并自行重新解释字节。
所以选择 bit-shifting:
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);
}
学究气 "@@@@"
的长度是 5,不是 4。