用constexpr中的工会替换reinterpret_cast-好主意吗?

时间:2019-04-05 11:02:47

标签: c++ c++11 union constexpr

我正在使用此代码将指针转换为IN,它用在size_t函数中,该函数应在编译时对给定的指针进行哈希处理,并且由于::std::hashreinterpret_cast中不允许使用,我想出了以下解决方案,它可以按预期工作,但是我想知道是否可以认为这是一个好主意。 如果您能给我一些有关这段代码的实际可移植性的指导,那也将是很棒的。

constexpr

有没有更好的解决方案-如上所述,我想创建一个在编译时运行的union { size_t datr; void* pointer; } dummy{.pointer = (void*) somePointer}; size_t pointerAsAsize_t = dummy.datr; // how portable is this?

2 个答案:

答案 0 :(得分:4)

如果您尝试在常量表达式上下文中执行该操作(即:当编译器在编译时被迫调用您的代码时,例如导致数组大小或模板参数的表达式),您会发现它将无法编译。 Constexpr执行要求在编译时会引起UB的任何事物都将采用错误的形式。而且由于您的代码会激怒UB(通过访问非活动的联合成员),因此它将无法编译。

All three major compilers will fail on this在常量表达式的上下文中。 MSVC(令人惊讶地)给出了最好,最直接的错误消息:

  

(13):错误C2131:表达式未求值为常量
  (9):注意:失败是由于访问工会的非活动成员引起的
  (9):注意:请参阅'foo :: Foo :: integer'

的用法

您的代码可能仅“按预期工作”,因为您在编译器不必在编译时执行代码时调用它。考虑到GCC / Clang的错误,如果将其用作堆栈上数组的数组大小,则它可能会调用GCC / Clang的可变长度数组语言扩展。如果将其关闭,则代码可能无法编译。我的示例将其设置为全局数组,不允许使用VLA。


  

有没有更好的解决方案

不。如果您提供指针(或包含指针的类型)作为源或目标,则即使C++20's bit_cast也不会是constexpr。编译时指针是真实的东西,不仅仅是代表地址的数字;它是真实的东西。在编译时将它们转换为整数或从整数转换绝对不是一个合理的活动。

编译时指针必须指向编译时存在的事物。 没有办法知道它们将指向运行时的位置。因此,从一开始就注定了对指针(甚至是指向静态/全局对象的指针)的编译时值进行哈希处理的想法。

答案 1 :(得分:-1)

我认为在大多数平台上,此代码都可以工作,但是从形式上讲它不能工作。 size_t是一个无符号类型,用于保存结果sizeof(xxx)的构造。无法保证其大小足以存储指针。您可以添加static_assert(sizeof(size_t) == sizeof(void*),"")或使用std::intptr_t(如果库中可用)。