Я пытаюсь создать constexpr union , который включает 3 типа. Объединение может содержать необработанные массивы uint8_t array
или фиксированной длины PODTypeA
или PODTypeB
. Длины этих массивов известны во время компиляции и задаются значениями constexpr.
Структуры POD очень просты:
struct PODTypeA {
int a;
int b;
};
или
struct PODTypeB {
uint32_t a;
uint32_t b;
};
Встроенная среда не имеет стандартной библиотеки шаблонов. Поэтому я не могу использовать constexpr std::array<T,N>
, который намного упростит задачу.
Ниже показана реализация массива 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 (извлекает) массив через компилятор для указанного члена объединения). Если бы кто-то мог объяснить, что это было бы плюсом. Я нашел описанный выше модуль расширения пакета параметров массива в проверенном ответе на следующее переполнение стека вопрос (где также есть живой пример).
Я поместил это в 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}};
^