是否可以将实现模板专门化定义为另一种类型的typedef?

时间:2013-12-06 09:01:34

标签: c++ templates c++11 typedef

我有一个类模板,我想介绍几个模板特化。那些模板特化与某些现有类型相同。从概念上讲,我想将它们实现为别名/ typedef。

以下示例代码应显示我想要执行的操作:

template<class T> class Common {
    /// general implementation
};

class TypeZ;    

template<> class Common<Type1> = TypeZ; // <<< how to do this?
template<> class Common<Type2> = TypeZ;
template<> class Common<Type3> = TypeZ;

上述在C ++(或C ++ 11)中是否可能以某种方式存在?如果我没有必要将Common<...>实现为继承TypeZ的类,那将会很棒 - 实际代码比上面显示的更复杂并且继承TypeZ不是很好那里的想法。

3 个答案:

答案 0 :(得分:10)

假设只有Common的某些特殊化是TypeZ的别名,那么你可以这样做:

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;

然后您使用common_t<T>而不是Common<T>

只是为了接受继承的想法,你试过这个吗?

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

然后您不需要使用嵌套类型别名。

答案 1 :(得分:4)

是的,您可以使用type aliases

template<typename T> using Common = TypeZ;

请参阅链接以获取更多可能的示例。 using可以在任何可以使用typedef的地方使用,也可以在上面的模板别名中使用,因此我建议您在编写C ++ 11的任何地方使用using而不是typedef。< / p>


如果您需要更复杂的映射,可以使用std::enable_ifstd::conditionalstd::is_same结合使用一些简单的模板元编程。 例如,如果您只需要专门针对3种类型,请使用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>(), "");

两个实现都等同于一个名称,并且您必须使用函数调用运算符()::value中的成员访问者std::conditional

答案 2 :(得分:0)

我不确定关于这个问题的代码在 C++ 标准中是否允许。
在我看来,'using' 将创建一个新的数据类型,请参阅下面的示例代码。

using TypeZ::TypeZ; 继承构造函数。

#include <iostream>

template<typename T>
class Base { using type_universal = T; };

//e.g. Normal template specialization
template<> class Base<int> { using type_int = int; };

//Target:
class TypeZ {public: int I_am_typeZ = 1; };

//Alias:
template<> class Base<double> : public TypeZ { using TypeZ::TypeZ; };

int main() {
    Base<double> instance;
    std::cout<<"Base<double>.I_am_typeZ = "<<instance.I_am_typeZ<<std::endl;

    return 0;
}