在编译时创建键值类型的所有可能映射的变体类型,其中键和值类型是从类型元组中指定的

时间:2018-03-26 12:46:58

标签: c++ templates variadic-templates template-meta-programming

目前,我有variantmap类型,我在其中硬编码键值对的所有变体,因此:

// for example, if we support std::string and int types as key-value pair
using MapCombinator = std::variant<
    std::map<std::string, std::string>, 
    std::map<std::string, int>, 
    std::map<int, std::string>, 
    std::map<int, int>>;

在实际情况中,除了std::string之外,我还需要支持所有基本类型的键值对。这就是为什么,我只想指定一个类型的元组,更像是这样:

using KVTypes = std::tuple<std::string, int, etc...>;
using MapCombinator = MapCombinatorImpl::type;

其中MapCombinatorImpl包含创建最终变体类型的模板元编程逻辑。我会期待这样的事情:

template<typename... SupportedTypes>
struct MapCombinatorImpl {
    typedef ??? type;
};

我不想为此使用宏,如果它与模板元编程太复杂,我只支持基本类型的可管理子集。

通过模板元编程实现帮助表示赞赏。

2 个答案:

答案 0 :(得分:2)

您可以使用2级参数包扩展:

namespace detail {
    template<class T, class... Ts>
    using pair_list = std::tuple<std::map<T, Ts>...>;

    template<class Tuple> struct huge_variant_impl;
    template<class... Ts>
    struct huge_variant_impl<std::tuple<Ts...>> {
        using type = std::variant<Ts...>;
    };
}

template<typename... Ts>
struct huge_variant {
    using type = typename detail::huge_variant_impl<
        decltype(std::tuple_cat(std::declval<detail::pair_list<Ts, Ts...>>()...))
        >::type;
};

答案 1 :(得分:2)

您可以使用:

template <typename Tuple, typename Seq> struct MapCombinatorImpl;

template <typename Tuple, std::size_t ... Is>
struct MapCombinatorImpl<Tuple, std::index_sequence<Is...>>
{
    constexpr static std::size_t size = std::tuple_size<Tuple>::value;
    using type = std::variant<std::map<std::tuple_element_t<Is / size, Tuple>,
                                       std::tuple_element_t<Is % size, Tuple>>...>;
};

template <typename ... Ts>
using MapCombinator =
    typename MapCombinatorImpl<std::tuple<Ts...>,
                               std::make_index_sequence<sizeof...(Ts) * sizeof...(Ts)>
                              >::type;

Demo