Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.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的编译时数组 //codenz.cpp constexpr uint32_t散列[]= { //ntdll crc32::生成(“memcpy”), //内核32 crc32::生成(“MessageBoxA”) }; //hash.hpp #包括 #包括 名称空间crc32 { //生成CRC查找表 模板 结构f:f>1),k-1>{}; 模板结构f{enum{value=c};}; #定义A(x)B(x)B(x+128) #定义B(x)C(x)C(x+64) #定义C(x)D(x)D(x+32) #定义D(x)E(x)E(x+16) #定义E(x)F(x)F(x+8) #定义F(x)G(x)G(x+4) #定义G(x)H(x)H(x+2) #定义H(x)I(x)I(x+1) #定义I(x)f::value, constexpr无符号crc_表[]={A(0)}; //Constexpr实现和帮助程序 constexpr uint32\u t crc32\u impl(constep uint8\u t*p,尺寸长度,uint32\u t crc){ 回蓝? crc32_impl(p+1,len-1,(crc>>8)^crc_表[(crc&0xFF)^*p]) :crc; } constexpr uint32\u t crc32(const uint8\u t*数据、大小和长度){ 返回~crc32_impl(数据,长度,~0); } constexpr size\u t strlen\u c(const char*str){ return*str?1+strlen_c(str+1):0; } constexpr uint32_t生成(const char*str){ 返回crc32((uint8_t*)str,strlen_c(str)); } }_C++_Arrays_C++11_Metaprogramming_Constexpr - Fatal编程技术网

C++ 带有constexpr的编译时数组 //codenz.cpp constexpr uint32_t散列[]= { //ntdll crc32::生成(“memcpy”), //内核32 crc32::生成(“MessageBoxA”) }; //hash.hpp #包括 #包括 名称空间crc32 { //生成CRC查找表 模板 结构f:f>1),k-1>{}; 模板结构f{enum{value=c};}; #定义A(x)B(x)B(x+128) #定义B(x)C(x)C(x+64) #定义C(x)D(x)D(x+32) #定义D(x)E(x)E(x+16) #定义E(x)F(x)F(x+8) #定义F(x)G(x)G(x+4) #定义G(x)H(x)H(x+2) #定义H(x)I(x)I(x+1) #定义I(x)f::value, constexpr无符号crc_表[]={A(0)}; //Constexpr实现和帮助程序 constexpr uint32\u t crc32\u impl(constep uint8\u t*p,尺寸长度,uint32\u t crc){ 回蓝? crc32_impl(p+1,len-1,(crc>>8)^crc_表[(crc&0xFF)^*p]) :crc; } constexpr uint32\u t crc32(const uint8\u t*数据、大小和长度){ 返回~crc32_impl(数据,长度,~0); } constexpr size\u t strlen\u c(const char*str){ return*str?1+strlen_c(str+1):0; } constexpr uint32_t生成(const char*str){ 返回crc32((uint8_t*)str,strlen_c(str)); } }

C++ 带有constexpr的编译时数组 //codenz.cpp constexpr uint32_t散列[]= { //ntdll crc32::生成(“memcpy”), //内核32 crc32::生成(“MessageBoxA”) }; //hash.hpp #包括 #包括 名称空间crc32 { //生成CRC查找表 模板 结构f:f>1),k-1>{}; 模板结构f{enum{value=c};}; #定义A(x)B(x)B(x+128) #定义B(x)C(x)C(x+64) #定义C(x)D(x)D(x+32) #定义D(x)E(x)E(x+16) #定义E(x)F(x)F(x+8) #定义F(x)G(x)G(x+4) #定义G(x)H(x)H(x+2) #定义H(x)I(x)I(x+1) #定义I(x)f::value, constexpr无符号crc_表[]={A(0)}; //Constexpr实现和帮助程序 constexpr uint32\u t crc32\u impl(constep uint8\u t*p,尺寸长度,uint32\u t crc){ 回蓝? crc32_impl(p+1,len-1,(crc>>8)^crc_表[(crc&0xFF)^*p]) :crc; } constexpr uint32\u t crc32(const uint8\u t*数据、大小和长度){ 返回~crc32_impl(数据,长度,~0); } constexpr size\u t strlen\u c(const char*str){ return*str?1+strlen_c(str+1):0; } constexpr uint32_t生成(const char*str){ 返回crc32((uint8_t*)str,strlen_c(str)); } },c++,arrays,c++11,metaprogramming,constexpr,C++,Arrays,C++11,Metaprogramming,Constexpr,正如您所看到的,函数本身和数组是constexpr,因此应该在编译时进行计算。MSVC编译器抛出一个错误“表达式的计算结果不是常量”。为什么呢 您应该删除冗余强制转换: // codenz.cpp constexpr uint32_t Hashes[] = { // ntdll crc32::generate("memcpy"), // kernel32 crc32::generate("MessageBo

正如您所看到的,函数本身和数组是
constexpr
,因此应该在编译时进行计算。MSVC编译器抛出一个错误“表达式的计算结果不是常量”。为什么呢

您应该删除冗余强制转换:

    // codenz.cpp
    constexpr uint32_t Hashes[] =
    {
        // ntdll
        crc32::generate("memcpy"),

        // kernel32
        crc32::generate("MessageBoxA")
    };

// hash.hpp
#include <cstring>
#include <cstdint>

namespace crc32
{
    // Generate CRC lookup table
    template <unsigned c, int k = 8>
    struct f : f<((c & 1) ? 0xedb88320 : 0) ^ (c >> 1), k - 1> {};
    template <unsigned c> struct f<c, 0> { enum { value = c }; };

    #define A(x) B(x) B(x + 128)
    #define B(x) C(x) C(x +  64)
    #define C(x) D(x) D(x +  32)
    #define D(x) E(x) E(x +  16)
    #define E(x) F(x) F(x +   8)
    #define F(x) G(x) G(x +   4)
    #define G(x) H(x) H(x +   2)
    #define H(x) I(x) I(x +   1)
    #define I(x) f<x>::value ,

    constexpr unsigned crc_table[] = { A(0) };

    // Constexpr implementation and helpers
    constexpr uint32_t crc32_impl(const uint8_t* p, size_t len, uint32_t crc) {
        return len ?
            crc32_impl(p + 1, len - 1, (crc >> 8) ^ crc_table[(crc & 0xFF) ^ *p])
            : crc;
    }

    constexpr uint32_t crc32(const uint8_t* data, size_t length) {
        return ~crc32_impl(data, length, ~0);
    }

    constexpr size_t strlen_c(const char* str) {
        return *str ? 1 + strlen_c(str + 1) : 0;
    }

    constexpr uint32_t generate(const char* str) {
        return crc32((uint8_t*)str, strlen_c(str));
    }
}
//现在我们只需要一个静态强制转换
constexpr uint32\u t crc32\u impl(const char*p,size\u t len,uint32\u t crc){
回蓝?
crc32_impl(p+1,len-1,(crc>>8)^crc_表[(crc&0xFF)^static_cast(*p)])
:crc;
}
constexpr uint32\u t crc32(const char*数据,大小\u t长度)
{
返回~crc32_impl(数据,长度,~0);
}
//我们可以一次性获得字符串文字数组大小
模板constexpr uint32\u t
生成(常量字符(&str)[V\u数组\u项目\u计数])
{
返回crc32(str,V_数组_项目_计数-1);
}


或者,如果您希望保持crc32接口接受
uint8\t
字节
,则可能需要在编译时构建相应的副本数组。

您应该删除冗余强制转换:

    // codenz.cpp
    constexpr uint32_t Hashes[] =
    {
        // ntdll
        crc32::generate("memcpy"),

        // kernel32
        crc32::generate("MessageBoxA")
    };

// hash.hpp
#include <cstring>
#include <cstdint>

namespace crc32
{
    // Generate CRC lookup table
    template <unsigned c, int k = 8>
    struct f : f<((c & 1) ? 0xedb88320 : 0) ^ (c >> 1), k - 1> {};
    template <unsigned c> struct f<c, 0> { enum { value = c }; };

    #define A(x) B(x) B(x + 128)
    #define B(x) C(x) C(x +  64)
    #define C(x) D(x) D(x +  32)
    #define D(x) E(x) E(x +  16)
    #define E(x) F(x) F(x +   8)
    #define F(x) G(x) G(x +   4)
    #define G(x) H(x) H(x +   2)
    #define H(x) I(x) I(x +   1)
    #define I(x) f<x>::value ,

    constexpr unsigned crc_table[] = { A(0) };

    // Constexpr implementation and helpers
    constexpr uint32_t crc32_impl(const uint8_t* p, size_t len, uint32_t crc) {
        return len ?
            crc32_impl(p + 1, len - 1, (crc >> 8) ^ crc_table[(crc & 0xFF) ^ *p])
            : crc;
    }

    constexpr uint32_t crc32(const uint8_t* data, size_t length) {
        return ~crc32_impl(data, length, ~0);
    }

    constexpr size_t strlen_c(const char* str) {
        return *str ? 1 + strlen_c(str + 1) : 0;
    }

    constexpr uint32_t generate(const char* str) {
        return crc32((uint8_t*)str, strlen_c(str));
    }
}
//现在我们只需要一个静态强制转换
constexpr uint32\u t crc32\u impl(const char*p,size\u t len,uint32\u t crc){
回蓝?
crc32_impl(p+1,len-1,(crc>>8)^crc_表[(crc&0xFF)^static_cast(*p)])
:crc;
}
constexpr uint32\u t crc32(const char*数据,大小\u t长度)
{
返回~crc32_impl(数据,长度,~0);
}
//我们可以一次性获得字符串文字数组大小
模板constexpr uint32\u t
生成(常量字符(&str)[V\u数组\u项目\u计数])
{
返回crc32(str,V_数组_项目_计数-1);
}


或者,如果您想让crc32接口接受
uint8\t
byte
,则可能需要在编译时构建相应的副本数组。

MSVC的constexpr支持随着时间的推移而不断改进。如果您使用的版本不能处理这种情况,我不会感到惊讶,但是如果没有一个或编译器版本,很难说。@chris我用一个完整的例子编辑了这篇文章。GCC也抱怨,尽管错误更好。MSVC的constexpr支持随着时间的推移一直在改进。如果您使用的版本不能处理这种情况,我不会感到惊讶,但是如果没有一个或编译器版本,很难说。@chris我用一个完整的例子编辑了这篇文章。GCC也会抱怨,尽管错误更好。感谢您的建议,幸运的是这并不能解决核心问题。@Swagov3rflow您所说的“不能解决核心问题”是什么意思。问题是,您有那些不能在常量表达式中使用的额外强制转换。当在数组外部使用它时,代码在更改之前运行良好(它在编译时生成了值,我对此进行了检查)。“核心问题”是它在数组中不工作。@Swagov3rflow“它在数组中不工作”是什么意思?“联机编译器链接”演示了仍然生成
哈希值
数组的完整工作示例。当使用您的更改(msvc编译器)在本地运行程序时,数组中的值为0。感谢您的建议,幸运的是,这并不能解决核心问题。@Swagov3rflow您的意思是什么“无法解决核心问题/问题”。问题是您有无法在常量表达式中使用的额外强制转换。在更改之前,代码在数组外部使用时运行良好(它在编译时生成了值,我对此进行了检查)。“核心问题”“它在数组中不工作。@Swagov3rflow“它在数组中不工作”是什么意思?联机编译器链接演示了仍然构建
哈希值
数组的完整工作示例。在本地运行带有更改的程序(msvc编译器)时,数组中的值为0。