【问题标题】:How to access a possibly unexisting type-alias in C++11?如何在 C++11 中访问可能不存在的类型别名?
【发布时间】:2015-11-07 14:01:32
【问题描述】:

我想写这样的东西:

template <class T>
using MyTypeOrTupple = typename std::conditional<has_member_type_MyType<T>::value,
                                                 typename T::MyType,
                                                 std::tuple<> >::type;

我使用https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector 实现了has_member_type_MyType

但是,当 MyType 未在 T 中定义时,GCC (4.8.4) 仍然抱怨使用 T::MyType。有没有办法解决这个问题?

【问题讨论】:

    标签: c++ templates c++11


    【解决方案1】:

    不要使用 Wikibooks 中那些疯狂的东西。

    template <class T>
    using MyType_t = typename T::MyType;
    
    template<class T> 
    using MyTypeOrTuple = detected_or_t<std::tuple<>, MyType_t, T>;
    

    其中detected_or_t 是库基础TS v2 中的std::experimental::detected_or_t,可以按如下方式实现:

    namespace detail {
    
        template<class...> struct voidify { using type = void; };
        template<class...Ts> using void_t = typename voidify<Ts...>::type;
    
        template <class Default, class AlwaysVoid,
                  template<class...> class Op, class... Args>
        struct detector {
          using value_t = std::false_type;
          using type = Default;
        };
    
        template <class Default, template<class...> class Op, class... Args>
        struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
          using value_t = std::true_type;
          using type = Op<Args...>;
        };
    
    } // namespace detail
    
    template <class Default, template<class...> class Op, class... Args>
    using detected_or = detail::detector<Default, void, Op, Args...>;
    
    template< class Default, template<class...> class Op, class... Args >
    using detected_or_t = typename detected_or<Default, Op, Args...>::type;
    

    【讨论】:

    • 谢谢!我根本不了解图书馆的基础知识。
    • 那个“疯狂”的东西是允许利用 SFINAE pre-C++11 和/或 void_t 概念之前的东西。
    【解决方案2】:
    template <typename...>
    struct voider { using type = void; };
    
    template <typename... Ts>
    using void_t = typename voider<Ts...>::type;
    
    template <typename, typename = void_t<>>
    struct MyTypeOrTupple { using type = std::tuple<>; };
    
    template <typename T> 
    struct MyTypeOrTupple<T, void_t<typename T::MyType>> { using type = typename T::MyType; };
    
    template <typename T>
    using MyTypeOrTupple_t = typename MyTypeOrTupple<T>::type;
    

    DEMO

    【讨论】:

    • 嗨 Piotr,你能简单解释一下为什么如果我设置 使用 void_t = void;编译器失败,为什么我需要“void_t”作为模板特化案例的第二个类型参数?
    • @Roman 见 thisthis
    【解决方案3】:

    我认为它需要 2 级间接:

    template<typename ...>
    struct void_type
    {
        using type = void;
    };
    
    template<typename ...T>
    using void_t = typename void_type<T...>::type;
    
    #define HAS_TYPE(NAME) \
    template<typename, typename = void> \
    struct has_type_##NAME: std::false_type \
    {}; \
    template<typename T> \
    struct has_type_##NAME<T, void_t<typename T::NAME>>: std::true_type \
    {}
    
    HAS_TYPE(MyType);
    
    template<typename T, bool = has_type_MyType<T>::value>
    struct MyTypeOrTupple_impl;
    
    template<typename T>
    struct MyTypeOrTupple_impl<T, true>
    { using type = typename T::MyType; };
    
    template<typename T>
    struct MyTypeOrTupple_impl<T, false>
    { using type = std::tuple<>; };
    
    template<typename T> using MyTypeOrTupple = typename MyTypeOrTupple_impl<T>::type;
    

    DEMO

    【讨论】:

      【解决方案4】:

      版本保持std::conditional:

      template <typename T> struct identity { using type = T; };
      template <typename T> struct MyType { using type = typename T::MyType; };
      
      template <class T>
      using MyTypeOrTupple =
          typename std::conditional<has_member_type_MyType<T>::value,
                                    MyType<T>,
                                    identity<std::tuple<>>>::type::type;
      

      【讨论】:

        猜你喜欢
        • 2012-01-04
        • 1970-01-01
        • 2011-08-31
        • 1970-01-01
        • 2012-12-27
        • 2011-01-26
        • 2017-03-29
        • 2015-07-21
        相关资源
        最近更新 更多