我可以reinterpret_cast constexpr函数的参数吗? [英] Can I reinterpret_cast the parameter of a constexpr function?

查看:108
本文介绍了我可以reinterpret_cast constexpr函数的参数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想编写一个在编译时求值的函数,它需要一个指向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")



  1. 如何修复 f()以便编译?

  2. 是否有更好的方法来实现相同的目标?

  1. How to fix f() so it compiles?
  2. 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 away const.
    • 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆