c++ - 用 constexpr 中的 union 替换 reinterpret_cast - 好主意?

标签 c++ c++11 constexpr unions

我正在使用这段代码将指针转换为 size_t , 它用于 ::std::hash应该在编译时散列给定指针的函数,自reinterpret_cast以来constexpr 中不允许使用 s ,我想出了以下解决方案,它按预期工作,但我想知道这是否可以被认为是一个好主意。 如果您能就这段代码的实际可移植性提供一些建议,那就太好了。

union {
   size_t datr;
   void* pointer;
} dummy{.pointer = (void*) somePointer};
size_t pointerAsAsize_t = dummy.datr; // how portable is this?

有没有更好的解决方案 - 如上所述,我想创建一个 ::std::hash<some_pointer*>在编译时运行。

最佳答案

如果您尝试在常量表达式上下文中执行该操作(即:当编译器在编译时被迫调用您的代码时,例如导致数组大小或模板参数的表达式),您会发现它不会编译。 Constexpr 执行要求任何在编译时会引发 UB 的东西都将变成病式的。并且由于您的代码引发了 UB(通过访问一个不活跃的 union 成员),它将无法编译。

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

(13): error C2131: expression did not evaluate to a constant
(9): note: failure was caused by accessing a non-active member of a union
(9): note: see usage of 'foo::Foo::integer'

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


Is there any better solution

没有。连C++20's bit_cast如果您提供指针(或包含指针的类型)作为源或目标,则不会是 constexpr。编译时指针是真实的东西,而不仅仅是代表地址的数字;在编译时将它们转换为整数/从整数转换根本不是合理的事件。

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

关于c++ - 用 constexpr 中的 union 替换 reinterpret_cast - 好主意?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55533976/

相关文章:

c++ - 使用 SDL2 和 MinGW 诊断 DLL 问题

c++ - 无法删除不需要的重载

c++ - 无法解析函数 'stof'

c++ - 此错误消息是否正确 : non-type template argument is not a constant expression

c++ - [decl.constexpr].5 到底是什么意思?

c++ - 如何将 NSObject 传递给 objective-c 中的 cpp 代码

c++ - 迭代器 - vector::iterator 和 array::iterator 的重载函数

c++ - C/C++ 头文件和代码文件中的 ASCII 艺术注释

c++ - 将 std::shuffle 与自定义随机数生成器一起使用?

c++ - 为什么不能使用 constexpr if (表达式) ,即使表达式可以在编译时求值