【问题标题】:Predefined type list passed to a std::variant传递给 std::variant 的预定义类型列表
【发布时间】:2019-01-25 18:20:05
【问题描述】:

有没有办法创建一个预定义的类型列表,并在 c++ 17 的 std::variant 中使用这些类型?这是我正在尝试做的事情,它可以编译,但没有像我希望的那样工作:

template < class ... Types > struct type_list {};
using valid_types = type_list< int16_t, int32_t, int64_t, double, std::string >;
using value_t = std::variant< valid_types >;

【问题讨论】:

    标签: c++ templates c++17 typelist std-variant


    【解决方案1】:

    一种方式:

    template<class... Types> 
    std::variant<Types...> as_variant(type_list<Types...>);
    
    using value_t = decltype(as_variant(valid_types{}));
    

    【讨论】:

    • 感谢您的回复,我相信这对我有用,我只需要准确地吸收这里发生的事情。如果我在这里错了,请纠正我。
    • 您正在声明一个返回类型变体的函数,该变体接受由有效类型别名的类型列表作为参数。 decltype 只是简单地返回 as_variant 将返回的内容?我理解正确吗?
    • @DavidMassat 是的,你说得对。注意as_variant函数定义在这里不是必须的,声明足以使用decltype
    【解决方案2】:

    这可以通过让type_listTypes 发送到元函数 (std::variant) 来完成:

    template < class ... Types > struct type_list {
        template < template < class... > class MFn >
        using apply = MFn< Types... >;
    };
    // Optional. For nicer calling syntax:
    template < template < class... > class MFn, class TypeList >
    using apply = typename TypeList::template apply< MFn >;
    
    using valid_types = type_list< int16_t, int32_t, int64_t, double, std::string >;
    using value_t = apply< std::variant, valid_types >;
    

    Godbolt link

    【讨论】:

    • 如果类型列表,您可能希望您的 apply 成为独立元函数而不是成员。
    • 由于value_type 是该上下文中的具体类型,我认为不需要value_t 行中的typenametemplate 关键字。
    • @Justin 语法会更好,你不需要template apply。与get 不是std::tuple 成员的原因相同。
    【解决方案3】:

    使用 Boost.MP11,这是mp_rename

    using value_t = mp_rename< valid_types, std::variant >;
    

    Godbolt link


    或者,mp_apply 与翻转操作数的操作相同,如果您觉得它更具可读性:

    using value_t = mp_apply< std::variant, valid_types >;
    

    【讨论】:

    • 我将其宣传为mp_rename&lt;valid_types, std::variant&gt;(同样的,只是颠倒了参数,但在这种情况下“重命名”更直接)。但是,是的,这绝对是最好的选择。很棒的图书馆。
    • @Barry 你说的“更直接”是什么意思?名字更明显吗?
    • 是的,我就是这个意思。我们基本上将type_list 重命名为variantapply 对我有不同的内涵。但无论哪种方式,我认为mp_apply 是根据mp_rename 定义的,所以没关系。
    【解决方案4】:

    这是我所知道的最短、最简洁的方法:

    template < class ... Types > struct type_list {
      template<template<class...>class Z>
      using apply_to = Z<Types...>;
    };
    
    using value_t = value_types::apply_to<std::variant>;
    

    你可以变得更漂亮。例如:

    template<class T, template<class...>class Z>
    struct transcribe_parameters;
    template<class T, template<class...>class Z>
    using transcribe_parameters_t = typename
      transcribe_parameters<T,Z>::type;
    template<template<class...>class Zin, class...Ts, template<class...>class Zout>
    struct transcribe_parameters<Zin<Ts...>, Zout> {
      using type=Zout<Ts...>;
    };
    

    给你:

    using value_t = transcribe_parameters_t<value_types, std::variant>;
    

    但是,将其作为 type_list 的内置功能似乎并不合理。

    【讨论】:

    • 请解释答案。
    【解决方案5】:

    如果您对扩充 type_list 结构感到满意:

    template <class ... Types> struct type_list {
        using variant_type = std::variant< Types...>;
    };
    

    如果你想把它作为一个单独的函数:

    template <class T> struct type_list_variant;
    template <class... Types> struct type_list_variant<type_list<Types...>> {
        using type = std::variant<Types...>;
    };
    
    template <class T>
    using type_list_variant_t = typename type_list_variant<T>::type;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 2019-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      相关资源
      最近更新 更多