1
\$\begingroup\$

Original question:

Enum list to STL container

Goal: Write a function enumToSTLContainer() that is to return any STL container whose elements are from a specified enum list.

The current solution below uses the assumption that the enum underlying values start at zero and are consecutive, and hence needs improvement. The solution is in C++11 rather than C++14 so that everyone here should be able to compile it.

#include <iostream>
#include <vector>
#include <set>

enum MyEnum {A, B, C, D, E, NumElements};

template <std::size_t...> struct index_sequence {};

template <std::size_t N, std::size_t... Is>
struct make_index_sequence_helper : make_index_sequence_helper<N-1, N-1, Is...> {};

template <std::size_t... Is>
struct make_index_sequence_helper<0, Is...> {
    using type = index_sequence<Is...>;
};

template <std::size_t N>
using make_index_sequence = typename make_index_sequence_helper<N>::type; 

template <typename RETURN_TYPE, std::size_t... TYPES>
inline RETURN_TYPE helper (index_sequence<TYPES...>) {
    return {static_cast<typename RETURN_TYPE::value_type>(TYPES)...};
}

template <typename CONTAINER, std::size_t N>
CONTAINER enumToSTLContainer() {
    return helper<CONTAINER> (make_index_sequence<N>());
}

int main() {
    const std::vector<MyEnum> enumVector = enumToSTLContainer<std::vector<MyEnum>, NumElements>();
    for (MyEnum x : enumVector)
        std::cout << x << ' ';  // 0 1 2 3 4
    const std::set<MyEnum> enumSet = enumToSTLContainer<std::set<MyEnum>, NumElements>();
    std::cout << "\n\n";
    for (MyEnum x : enumSet)
        std::cout << x << ' ';  // 0 1 2 3 4
}

I would appreciate if someone could show me how to improve this solution where the enum underlying values are not consecutive. Ideally NumElements should not be needed either. I presume only make_index_sequence_helper needs to be modified according the MyEnum underlying values?

The only generalization that I could come up with is the lousy:

template <typename CONTAINER, std::size_t... Is>
CONTAINER enumNonContiguousToSTLContainer() {
    return helper<CONTAINER> (index_sequence<Is...>());
}
\$\endgroup\$
  • 2
    \$\begingroup\$ Iterating over a non-contiguous enum in a generic way is impossible with standard C++. Enums don't support any notion of iteration, so there's not really much you can do that's not specific to each enum. \$\endgroup\$ – Corbin Oct 26 '14 at 20:17
  • \$\begingroup\$ Is this for an arbitrary enum or one whose definition you control? The only ways to do something like this I know of involve macro trickery. \$\endgroup\$ – mattnewport Oct 31 '14 at 4:50
  • \$\begingroup\$ I believe this would be possible with some template trickery if there was a way to distinguish integers that were valid enum values at compile time but I don't know of any way to do that. \$\endgroup\$ – mattnewport Oct 31 '14 at 18:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.