如何从 constexpr 表达式中的 const void* 进行转换?

How to cast from const void* in a constexpr expression?

我正在尝试将 memchr 重新实现为 constexpr (1​​)。我没有预料到问题,因为我已经用非常相似的 strchr 成功地完成了同样的事情。

但是 clang 和 gcc 都拒绝将 const void* 强制转换为 constexpr 函数中的任何其他内容,这使我无法访问实际值。

我知道在 constexpr 函数中使用 void* 很奇怪,因为我们不能执行 malloc 并且无法将任意数据指定为文字值。我这样做基本上是作为练习的一部分,尽可能多地重写 as constexpr (2)。

我仍然想知道为什么不允许这样做,以及是否有任何解决方法。

谢谢!

(1) 我的memchr实现:

constexpr void const *memchr(const void *ptr, int ch, size_t count) {
    const auto block_address = static_cast<const uint8_t *>(ptr);
    const auto needle = static_cast<uint8_t>(ch);
    for (uintptr_t pos{0}; pos < count; ++pos) {
        auto byte_address = block_address + pos;
        const uint8_t value = *byte_address;
        if (needle == value) {
            return static_cast<void const *>(byte_address);
        }
    }
    return nullptr;
}

(2) Github 上的整个项目:https://github.com/jlanik/constexprstring

不,不可能在常量表达式中以这种方式使用void*。在常量表达式中禁止从 void* 转换为其他对象指针类型。 reinterpret_cast 也被禁止。

这可能是故意的,以便在编译时无法访问对象表示。

您不能在编译时使用具有通常签名的 memchr

我认为你能做的最好的事情是编写指向 char 及其 cv 限定版本的指针的函数,以及 std::byte (作为重载或模板),而不是void*.

对于指向其他类型对象的指针,在某些情况下会很棘手,在大多数情况下不可能实现 memchr.

的确切语义。

虽然我不确定这是否可能,但也许,在 memchr 的模板化版本中,可以通过 std::bit_cast 读取指针传递的对象的底层字节到包含适当大小的 std::byte/unsigned char 数组的结构。