是否可以在编译时使用 C++ 可变参数模板构建 const 数组?

是否可以在编译时使用 C++ 可变参数模板构建 const 数组?

问题描述:

以下代码尝试创建一种类型安全的方式来生成字节支持的二进制数据,同时自动生成描述字节的元数据.有没有办法在编译时生成元数据?例如:

The following code attempts to create a typesafe way to generate byte-backed binary data while automatically generating metadata describing the bytes. Is there any way to generate the metadata at compile time? For example:

const Type meta[] = {Type::U32, Type::U64};

我什至不确定这是否可行,但如果可以,请告诉我怎么做!

I'm not even sure that's possible, but if it is please tell me how!

#include <iostream>
using namespace std;

enum class Type { U8, U16, U32, U64, I8, I16, I32, I64, F32, F64, STRUCT };

void write(char*& buf, uint32_t val) {
    *(uint32_t*)buf = val;
    buf += sizeof(uint32_t);
}

void write(char*& buf, uint64_t val) {
    *(uint64_t*)buf = val;
    buf += sizeof(uint64_t);
}

void writeMeta(char*& buf, uint32_t val) {
    *(uint8_t*)buf = uint32_t(Type::U32);
    buf += sizeof(uint8_t);
}

void writeMeta(char*& buf, uint64_t val) {
    *(uint8_t*)buf = uint32_t(Type::U64);
    buf += sizeof(uint8_t);
}

void writeBuf(char* buf, char*meta) {
}

template<typename T, typename ...Args>
void writeBuf(char* buf, char*meta, T first, Args... args) {
  write(buf, first);
    writeMeta(meta, first);
    writeBuf(buf, meta, args...);
}

int main() {
    char buffer[1024];
    char metadata[1024];
    writeBuf(buffer, metadata, uint32_t(2), uint64_t(3));
    for (int i = 0; i < 12; i++)
        cout << uint32_t(uint8_t(buffer[i])) << ' ';
    cout << '\n';
}

据我所知,您需要类似 (C++17) 的内容:

As I understand, you want something like (C++17):

template <typename T>
constexpr Type toType()
{
    if constexpr (std::is_same_v<uint8_t, T>) { return Type::U8; }
    else if constexpr (std::is_same_v<uint16_t, T>) { return Type::U16; }
    else if constexpr (std::is_same_v<uint32_t, T>) { return Type::U32; }
    // ...
    else { return Type::STRUCT; }
}

template <typename ...Ts>
constexpr std::array<Type, sizeof...(Ts)> getMeta()
{
    return {{toType<Ts>()...}};
}

static_assert(getMeta<std::uint32_t, std::uint64_t>() == {Type::U32, Type::U64});