Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在constexpr/consteval上下文中,是否有任何方法可以访问作为字符数组的已知大小的任意数据?_C++_Gcc_Constexpr_C++20_Consteval - Fatal编程技术网

C++ 在constexpr/consteval上下文中,是否有任何方法可以访问作为字符数组的已知大小的任意数据?

C++ 在constexpr/consteval上下文中,是否有任何方法可以访问作为字符数组的已知大小的任意数据?,c++,gcc,constexpr,c++20,consteval,C++,Gcc,Constexpr,C++20,Consteval,我正在尝试实现一些东西,它将接收任意位的数据(在编译时已知),并将它们的CRC计算为consteval,因此我可以使用它来索引这些数据,例如使用整数键,而不需要任何运行时开销。当输入是字符字符串文字时,我可以让它工作,但当输入是wchar\tstring文字时,我很难让它工作 我得到一个相当神秘的错误 错误:通过常量表达式中的“const char”glvalue访问“T\000e\000s\000t\000\000”的值 。。。这似乎是由于在constexpr上下文中使用reinterpret

我正在尝试实现一些东西,它将接收任意位的数据(在编译时已知),并将它们的CRC计算为
consteval
,因此我可以使用它来索引这些数据,例如使用整数键,而不需要任何运行时开销。当输入是字符字符串文字时,我可以让它工作,但当输入是
wchar\t
string文字时,我很难让它工作

我得到一个相当神秘的错误

错误:通过常量表达式中的“const char”glvalue访问“T\000e\000s\000t\000\000”的值

。。。这似乎是由于在constexpr上下文中使用reinterpret_cast造成的(这显然是不允许的)

我的问题是,有没有办法将任意数据解释为一个普通的字节数组?我不在乎它有多丑陋或缺乏可移植性(只要它都发生在编译时)。现在,只要用
wchar\u t
数组作为输入来解决这个问题就足够了。显然,我可以“只是”为我想要单独处理的每种类型重新实现CRC计算,但如果可能的话,我宁愿不这样做(事实上,对于任何比POD数组更复杂的事情,这都是相当棘手的)

失败代码如下所示,以供参考:

// Details of CRCInternal omitted for brevity
template <size_t len> consteval uint32_t CRC32(const char (&str)[len])
{
    return CRCInternal::crc32<len - 1>(str) ^ 0xFFFFFFFFu;
}

template <size_t len> consteval uint32_t CRC32FromWide(const wchar_t (&filename)[len])
{
    return CRC32(reinterpret_cast<const char(&)[len * sizeof(wchar_t)]>(filename));
}

void main()
{
    CRC32FromWide(L"Test"); // <==== Error
}
//为了简洁起见,省略了CRC内部的详细信息
模板consteval uint32\u t CRC32(const char和str)[len])
{
返回CRCInternal::crc32(str)^0xFFFFFFFFu;
}
模板consteval uint32\u t crc32 fromwide(const wchar\u t(&filename)[len])
{
返回CRC32(重新解释强制转换(文件名));
}
void main()
{

CRC32全屏幕(L“测试”)C++对象模型通常是虚构的,程序员编写代码和编译器生成二进制可执行文件之间的协议。对于可执行文件,对象不存在;它只是存储在内存中的位。因此,可以利用C++有几十个后门,可以用来有效地假装对象。ct模型是不真实的。其中许多模型被声明为表现出未定义的行为,但没有编译器会检查这些违反对象模型的行为并阻止您。您违反了合同,但编译器没有注意到,因此您可以逍遥法外

常量表达式求值的情况并非如此。已编译的可执行文件在CPU上运行;常量表达式求值在编译器内运行。对象模型不必映射到“位”或“内存”或任何类似的东西;它可以是具有全生命周期跟踪和分析的真实对象模型

<> P> C++标准因此要求,在不断的评估中,如果你做任何显示UB的事情,编译器必须检测到这个,并声明你的程序不正确。而且,CONTXPR代码是完全禁止使用最大的后门:<代码> RealTytCase 在编译时,对象不是存储中的字节,所以您不能像对待字节那样对待它们

这一点尤其重要,因为编译器的执行环境和最终二进制文件的执行环境不必相同。如果您正在为某些嵌入式系统进行开发,则目标CPU的endian可能与编译器执行的CPU的endian不匹配。因此,如果您能够如果将任何编译时数据仅作为字节,那么在编译时您将得到与运行时不同的答案

那太糟糕了

C++20的
std::bit_cast
存在并可以提供帮助,但即使这样也不能做所有事情。类型仅适用于
constexpr
bit_cast
-ing,前提是它是可复制的,并且不存储指针(除其他外)这是因为编译时指针不仅仅是地址;它们是一种复杂的数据类型,必须记住它指向的对象(否则,当您将它们转换为不相关的类型并试图通过错误的类型访问对象时,将无法检测到)

但是如果您将类型限制为
constepr
bit\u cast
able,那么您可以
bit\u cast
将它们设置为大小相同的数组


请注意,
constexpr
bit\u cast
并不是最容易实现的,因为它必须使源对象数据像在目标CPU和环境上执行一样工作,而不是在编译器正在执行的环境中。因此,如果目标是一台大端计算机,而源是小端计算机,
constexpr
bit_cast
必须进行endian转换,并且必须在具体了解源对象和目标对象的每个组件类型的情况下进行这种转换。

怎么样?事实上,这似乎正是我需要的!不幸的是,除了MSVC之外,似乎还没有其他编译器能够完全实现它…wh我想这是一个强烈的暗示,没有编译器的支持是不可能成功的。我希望现在有一种方法可以在编译器中实现这一点,不管它有多粗糙(对于我的用例,我永远不必担心endianness之类的问题,所以我真的不介意不正确地处理它),但目前我所能做的似乎只是等待编译器真正实现
位转换
(或者切换到MSVC,这目前不是一个选项)。我会将此标记为已解决。