Search code examples
c++arraysdictionaryconstexprstatic-assert

How to initialize a map of arrays of different sizes?


Simple question, how to initialize a map of arrays (or some other container type) of different sizes? For example:

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}}

};

I need to find at compile time if res::X2 is in map name at code::B

This expression should, I think, check for that using 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)));
}

Because validate is a constexpr a basic array would work but how to define it in a map argument as an array of type res? And that each array could be different in size?

So, I've made a mistake. I was under the impression that map can be accessed in constexpr function. What container type can you suggest me that would allow me to achieve what I have written above?


Solution

  • Since std::map can't be used in constexpr expression I was forced to find another solution and thanks to @kfsone and @H. Guijt for pointing that out as well as mentioning std::initializer_list and std::array which lead me to this solution.

    Since the data in the map in the question will be constant, i can do without an associative container. So I used a sorted array of std::initializer_lists together with a constexpr implementation of find function which works great for my needs.

    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");