简单的问题,如何初始化不同大小的数组(或其他容器类型)的映射?例如:
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
位于地图name
code::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
类型的数组?并且每个阵列的大小可能不同?
所以,我犯了一个错误。我的印象是可以在constexpr函数中访问地图。您可以建议我使用哪种容器类型来实现我上面所写的内容?
答案 0 :(得分:1)
如果数组可以是常量,则可以正常工作:
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函数中的地图。
答案 1 :(得分:0)
你不能在constexpr表达式中使用std::map
,尤其是因为它有一个非平凡的析构函数(标准中指定的~map();
)。
如果您搜索constexpr标准的map
部分,则无法找到它(http://eel.is/c++draft/map),而您将std::array
(http://eel.is/c++draft/array.syn)< / p>
答案 2 :(得分:0)
由于std::map
无法在constexpr
表达式中使用,因此我被迫寻找另一种解决方案,感谢@kfsone和@H。 Guijt指出了这一点,并提到引导我解决这个问题的std::initializer_list
和std::array
。
由于问题中地图中的数据是常量,我可以不使用关联容器。因此,我使用了std::initializer_list
s的排序数组以及查找函数的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");