代码之家  ›  专栏  ›  技术社区  ›  Infinity

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

  •  1
  • Infinity  · 技术社区  · 6 年前

    目前,我有一个 variant 属于 map 类型,其中我硬编码键值对的所有变体,例如:

    // 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 回复  |  直到 6 年前
        1
  •  2
  •   Jarod42    6 年前

    您可以使用:

    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

        2
  •  2
  •   llllllllll    6 年前

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

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