Is it possible to define an implementation template specialization as typedef of another type?

前端 未结 2 910
你的背包
你的背包 2021-01-17 14:15

I have a class template for which I want to introduce several template specializations. Those template specializations identical to some existing type. Conceptually I would

相关标签:
2条回答
  • 2021-01-17 14:41

    Assuming only certain specialisations of Common are aliases of TypeZ then you can do:

    template<class T> class Common {
        struct type {
            /// general implementation
        };
    };
    
    template<> class Common<Type1> { using type = TypeZ; };
    template<> class Common<Type2> { using type = TypeZ; };
    template<> class Common<Type3> { using type = TypeZ; };
    
    template<class T> using common_t = typename Common<T>::type;
    

    Then you use common_t<T> rather than Common<T>.

    Just to entertain the inheritance idea, have you tried this?

    template<> class Common<Type1> : public TypeZ { using TypeZ::TypeZ; };
    template<> class Common<Type2> : public TypeZ { using TypeZ::TypeZ; };
    template<> class Common<Type3> : public TypeZ { using TypeZ::TypeZ; };
    

    Then you don't need to use a nested type alias.

    0 讨论(0)
  • 2021-01-17 14:43

    Yes you can, by using type aliases:

    template<typename T> using Common = TypeZ;
    

    See the link for more examples of what is possible. using can be used anywhere typedef can be used, plus in template aliases like the above, so I recommend using using over typedef everywhere you write C++11.


    If you need a more complicated mapping, you can use some simple template metaprogramming using std::enable_if or std::conditional combined with std::is_same. For example, if you need to specialize for 3 types only, use this:

    #include <type_traits>
    
    class Type1 {};
    class Type2 {};
    class Type3 {};
    class Type4 {};
    
    class TypeZ {};
    
    // Implementation 1
    template<typename T>
    constexpr bool is_Type123_func()
    {
      return std::is_same<T, Type1>() || std::is_same<T, Type2>() || std::is_same<T, Type3>();
    }
    template<typename T>
    using Common_byfunc = typename std::conditional<is_Type123_func<T>(), TypeZ, T>::type;
    
    static_assert(std::is_same<Common_byfunc<Type1>, TypeZ>(), "");
    static_assert(std::is_same<Common_byfunc<Type2>, TypeZ>(), "");
    static_assert(std::is_same<Common_byfunc<Type3>, TypeZ>(), "");
    static_assert(!std::is_same<Common_byfunc<Type4>, TypeZ>(), "");
    
    // Implementation 2
    template<typename T>
    struct is_Type123 : public std::conditional<std::is_same<T, Type1>() || std::is_same<T, Type2>() || std::is_same<T, Type3>(), std::true_type, std::false_type>::type {};
    template<typename T>
    using Common = typename std::conditional<is_Type123<T>::value, TypeZ, T>::type;
    
    static_assert(std::is_same<Common<Type1>, TypeZ>(), "");
    static_assert(std::is_same<Common<Type2>, TypeZ>(), "");
    static_assert(std::is_same<Common<Type3>, TypeZ>(), "");
    static_assert(!std::is_same<Common<Type4>, TypeZ>(), "");
    

    Both implementations are equivalent up to a name and the fact you have to use a function call operator () or the member accessor ::value in the std::conditional.

    0 讨论(0)
提交回复
热议问题