Template aliase
有两种实现方式:
1、C++11 using
2、Type-Generator idiom(参见Type-Generator
章节)
wikipedia C++11#Template aliases
NOTE: 它介绍了引入
using
的原因
C++ typedef for partial templates
stackoverflow C++ typedef for partial templates
template< class A, class B, class C >
class X
{
};
template< class B, class C >
typedef X< std::vector<B>, B, C > Y;
使用c++11 using
的写法
template< class A, class B, class C >
class X
{
};
template <typename B, typename C>
using Y = X< std::vector<B>, B, C >;
不使用c++11 using
的写法
template< class A, class B, class C >
class X
{
};
template<class B, class C>
struct Y {
typedef X<std::vector<B>, B, C> type;
};
在drdobbs The New C++: Typedef Templates中对上述这种不使用c++11 using
的写法进行了介绍,下面是其中给出的example
template< typename T >
struct SharedPtr
{
typedef Loki::SmartPtr
<
T, // note, T still varies
RefCounted, // but everything else is fixed
NoChecking,
false,
PointsToOneObject,
SingleThreaded,
SimplePointer<T> // note, T can be used as here
>
Type;
};
SharedPtr<int>::Type p; // sample usage, "::Type" is ugly
probablydance Alias templates with partial specialization, SFINAE and everything
template<typename T>
using MyVector = std::vector<T, MyAllocator<T>>; // alias-declaration
MyVector<T> myvector; // instantiating with MyAllocator;
template<size_t Size, typename T>
struct Vector
{
T elements[Size];
//...
Vector operator*(const T & rhs) const
{
Vector copy(*this);
for (T & element : copy.elements)
{
element *= rhs;
}
return copy;
}
//...
};
typedef Vector<2, float> Vec2f;
typedef Vector<3, float> Vec3f;
To get my code to compile I would either have to define my multiplication operator above twice, or I would have to add a conversion operator to Vector<1, float>
. Both of which I didn’t want to do, because really I wanted Vector<1, float>
to be the same as just float
. Meaning I wanted
static_assert(std::is_same<Vector<1, float>, float>::value, "a scalar is a scalar");
So this is where I wanted an alias-declaration with a partial specialization. Which the standard forbids. Turns out you can solve that by adding a layer of indirection. This is my solution:
namespace detail
{
template<size_t Size, typename T>
struct Vector
{
// the code from above goes here
};
template<size_t Size, typename T>
struct VectorTypedef
{
typedef Vector<Size, T> type;
};
template<typename T>
struct VectorTypedef<1, T>
{
typedef T type;
};
}
template<size_t Size, typename T>
using Vector = typename detail::VectorTypedef<Size, T>::type;
Which is exactly what I wanted. If you think about this, this actually makes templates more powerful than they were in C++03. In C++03 you could create templates that were completely different structs depending on the template arguments,like std::vector<bool>
vs. std::vector<unsigned char>
, but the classes would always have to be related. You could never have an unrelated type from a library or a fundamental type behind a template. Now you can.
Example
C++11的using
就是用来解决这个问题的,在internalpointers The differences between "using" and "typedef" in modern C++中对此进行了介绍。
template<typename T1, typename T2>
using Map = std::map<T1, std::vector<T2>>;
template <size_t N>
using Vector = Matrix<N, 1>;
C++14 TransformationTrait
参见 C++\What-is-new-in-C++\C++14\TransformationTrait
章节。