如何初始化不同大小数组的映射?

How to initialize a map of arrays of different sizes?

简单的问题,如何初始化不同大小的数组(或其他一些容器类型)的映射?例如:

enum class code {A,B,C};
enum class res {X1,X2,X3,X4,X5};

std::map<code, ?> name {
    {code:A, {res::X1,res::X2}},
    {code:B, {res::X2,res::X3, res::X4}},
    {code:C, {res::X5}}

};

我需要在编译时查找 res::X2 是否在地图 namecode::B

我认为这个表达式应该使用 static_assert:

检查
constexpr bool validate(code t, res p, int i = 0) {
    return (name[t][i] == p ? true : ((sizeof(name[t]) == (i+1)) ? false :validate(t, p, ++i)));
}

因为 validate 是一个 constexpr 基本数组可以工作,但是如何在 map 参数中将其定义为 res 类型的数组?而且每个数组的大小可能不同?

所以,我犯了一个错误。我的印象是 map 可以在 constexpr 函数中访问。您可以建议我使用哪种容器类型来实现我上面写的内容?

如果数组是 const 没问题,这行得通:

std::map<code, std::initializer_list<res>> name {
    {code::A, {res::X1,res::X2}},
    {code::B, {res::X2,res::X3, res::X4}},
    {code::C, {res::X5}}
};

如果你需要能够写入数组,你需要这样的东西:

std::map<code, std::vector<res>> name {
    {code::A, {res::X1,res::X2}},
    {code::B, {res::X2,res::X3, res::X4}},
    {code::C, {res::X5}}
};

这将以额外的内存分配为代价,因为向量是在堆上分配的。

如果您希望它是可写的并且可以使用固定大小,这也可以避免额外的分配:

std::map<code, std::array<res, 3>> name {
    {code::A, {res::X1,res::X2}},
    {code::B, {res::X2,res::X3, res::X4}},
    {code::C, {res::X5}}
};

至于你问题的第二部分,鉴于你无法在 constexpr 函数中访问地图,我不太确定 any 解决方案是否有效。

不能 在 constexpr 表达式中使用 std::map,尤其是因为它有一个非平凡的析构函数(~map(); 在标准)。

如果您搜索 constexpr 标准的 map 部分,您将找不到它 (http://eel.is/c++draft/map), whereas you will for std::array (http://eel.is/c++draft/array.syn)

因为 std::map 不能用在 constexpr 表达式中,我被迫寻找另一个解决方案,感谢@kfsone 和@H。 Guijt 指出了这一点并提到了 std::initializer_liststd::array 这让我找到了这个解决方案。

由于问题中地图中的数据是不变的,我可以不用关联容器。因此,我将 std::initializer_list 的排序数组与查找函数的 constexpr 实现一起使用,这非常适合我的需要。

template <class It, class T>
inline constexpr It sfind (It begin, It end, T const& value) noexcept
{
    return ! (begin != end && *begin != value)? begin : sfind (begin+1, end, value);
}

enum class code {A,B,C};
enum class res {X1,X2,X3,X4,X5};

constexpr std::array<std::initializer_list<res>, 3> name {{
    {res::X1,res::X2}, //code::A
    {res::X2,res::X3, res::X4}, //code::B
    {res::X5} // code::C

}};
const code c = code::A;
const res r = res::X3;
static_assert (name[static_cast<int>(c)].end () - sfind(name[static_cast<int>(c)].begin(), name[static_cast<int>(c)].end(), r) != 0,"Not found");