首页 > 解决方案 > constexpr 与使用参数包扩展的 POD 结构成员联合

问题描述

我正在尝试构建一个包含 3 种类型的constexpr 联合。联合可以包含原始 uint8_t或或array的固定长度数组。这些数组的长度在编译时是已知的,并由 constexpr 值给出。PODTypeAPODTypeB

POD 结构非常简单:

struct PODTypeA {
    int a;
    int b;
};

或者

struct PODTypeB {
    uint32_t a;
    uint32_t b;
};

嵌入式环境没有可用的标准模板库。因此,我不能使用constexpr std::array<T,N>which 会使事情变得容易得多。

下面显示的是一个constexpr Array(const Args&... args)数组实现,它应该作为一个 constexpr 数据成员来保存数组字段。

template <typename T, std::size_t Size>
struct Array {
    T data[Size];
    template <typename ...Args>
    constexpr Array(const Args&... args)
        : data{ args... }
    {}
};

我不完全理解参数包扩展是如何工作的(通过编译器有效地 memcpy(ing) 数组到指定的联合成员)。如果有人可以解释这将是一个加号。我在以下堆栈溢出问题的检查答案中找到了上述 Array 模板参数包扩展器(其中还有一个现场示例)。

我把它放在一个coliru项目中,但我有很多编译问题。

我有 3 个联合构造函数,每一个都采用固定长度的数组参数,如下所示:

constexpr static auto gSizeBytes = 2048;
constexpr static int gArraySizeA = 2;
constexpr static int gArraySizeB = 3;

union UnionStruct {

    explicit constexpr UnionStruct(
        const uint8_t(&rParam)[gSizeBytes] = {})
        : byteArray(rParam)
    {}

    explicit constexpr UnionStruct(
        const PODTypeA(&rParam)[gArraySizeA])
        : arrayA(rParam)
    {}

    explicit constexpr UnionStruct(
        const PODTypeB(&rParam)[gArraySizeB])
        : arrayB(rParam)
    {}

    Array<uint8_t, gSizeBytes> byteArray;
    Array<PODTypeA, gArraySizeA> arrayA;
    Array<PODTypeB, gArraySizeB> arrayB;
};

这是我期望的使用方式:

int main()
{
    PODTypeA[UnionStruct::gArraySizeA] arrayTypeA = {{1,2}, {3,4}};
    // construct union from fixed PODTypeA array with 2 elements
    UnionStruct foo (arrayTypeA);
}

编译器发出以下错误:

g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In instantiation of 'constexpr Array<T, Size>::Array(const Args& ...) [with Args = {unsigned char [2048]}; T = unsigned char; long unsigned int Size = 2048]':
main.cpp:34:27:   required from here
main.cpp:12:25: error: invalid conversion from 'const unsigned char*' to 'unsigned char' [-fpermissive]
         : data{ args... }
                         ^
main.cpp: In instantiation of 'constexpr Array<T, Size>::Array(const Args& ...) [with Args = {PODTypeA [2]}; T = PODTypeA; long unsigned int Size = 2]':
main.cpp:39:24:   required from here
main.cpp:12:25: error: invalid conversion from 'const PODTypeA*' to 'int' [-fpermissive]
main.cpp: In instantiation of 'constexpr Array<T, Size>::Array(const Args& ...) [with Args = {PODTypeB [3]}; T = PODTypeB; long unsigned int Size = 3]':
main.cpp:44:24:   required from here
main.cpp:12:25: error: invalid conversion from 'const PODTypeB*' to 'uint32_t' {aka 'unsigned int'} [-fpermissive]
main.cpp: In function 'int main()':
main.cpp:54:14: error: expected identifier before numeric constant
     PODTypeA[2] arrayTypeA = {{1,2}, {3,4}};
              ^
main.cpp:54:14: error: expected ']' before numeric constant
     PODTypeA[2] arrayTypeA = {{1,2}, {3,4}};
              ^
              ]
main.cpp:54:13: error: structured binding declaration cannot have type 'PODTypeA'
     PODTypeA[2] arrayTypeA = {{1,2}, {3,4}};
             ^
main.cpp:54:13: note: type must be cv-qualified 'auto' or reference to cv-qualified 'auto'
main.cpp:54:13: error: empty structured binding declaration
main.cpp:54:17: error: expected initializer before 'arrayTypeA'
     PODTypeA[2] arrayTypeA = {{1,2}, {3,4}};
                 ^~~~~~~~~~
main.cpp:56:22: error: 'arrayTypeA' was not declared in this scope
     UnionStruct foo (arrayTypeA);
                      ^~~~~~~~~~
main.cpp:56:22: note: suggested alternative: 'gArraySizeA'
     UnionStruct foo (arrayTypeA);
                      ^~~~~~~~~~
                      gArraySizeA
main.cpp:54:13: warning: unused structured binding declaration [-Wunused-variable]
     PODTypeA[2] arrayTypeA = {{1,2}, {3,4}};
             ^

标签: c++c++11c++17unionconstexpr

解决方案


推荐阅读