枚举列表到STL容器

时间:2014-10-26 15:47:17

标签: c++ stl enums

有人能改进我的这个功能吗? enumToSTLContainer将返回其元素来自指定枚举列表的任何STL容器。

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

enum MyEnum {A, B, C, D, E, FirstMyEnum = A, LastMyEnum = E};

template <typename CONTAINER>
CONTAINER enumToSTLContainer (typename CONTAINER::value_type first, typename CONTAINER::value_type last) {
    CONTAINER v;
    for (typename std::underlying_type<typename CONTAINER::value_type>::type N = first;  N <= last;  N++)
        v.push_back(static_cast<typename CONTAINER::value_type>(N));  // But only works for STL containers with push_back defined.
    return v;
}

int main() {
    const std::vector<MyEnum> enumVector = enumToSTLContainer<std::vector<MyEnum>> (FirstMyEnum, LastMyEnum);
    for (MyEnum x : enumVector)
        std::cout << x << ' ';  // 0 1 2 3 4
//  const std::set<MyEnum> enumSet = enumToSTLContainer<std::set<MyEnum>> (FirstMyEnum, LastMyEnum);  // won't compile
}

以上问题。仅适用于定义了push_back的STL容器,需要指定枚举列表的第一个和最后一个元素,如果枚举值不连续,则不起作用,...

也许使用variadic模板获取initializer_list,然后可以返回所需的STL容器?使用std :: integer_sequence从枚举中创建一个元组,或者在枚举元素不连续时创建自己的integer_sequence?

1 个答案:

答案 0 :(得分:1)

好的,我使用以下内容获得了所需的属性,但它使用了枚举基础值从零开始并且是连续的假设。解决方案是使用C ++ 11而不是C ++ 14,因此这里的每个人都应该能够编译它。

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

因此,使用第二个解决方案,我们不再局限于具有push_back的STL容器。如果有人能告诉我如何改进这个枚举基础值不连续的解决方案,我将不胜感激。理想情况下,也不需要NumElements。我假设只需要根据MyEnum底层值修改make_index_sequence_helper?

我能想出的唯一概括是糟糕的:

template <typename CONTAINER, std::size_t... Is>
CONTAINER enumNonContiguousToSTLContainer() {
    return helper<CONTAINER> (index_sequence<Is...>());
}