有一个类似A的类,有没有办法将它应用到像B这样的模板,T2设置为某种类型C?但是没有创建继承自A。
的另一个模板类template<typename T1, typename T2>
class A
{ };
template<template <typename T1> class T3>
class B
{ };
答案 0 :(得分:3)
使用模板别名的C ++ 11工作:
template<typename T1, typename T2>
class A
{ };
template<template <typename T1> class T3>
class B
{ };
class C
{ };
template< typename T > using A1 = A< T, C >;
int main()
{
B< A1 > b;
}
没有C ++ 11,你可能已经知道了:
template< typename T > class A1 : A< T, C > {};
答案 1 :(得分:2)
我将提出另一种解决方案:不要使用模板模板参数。
如果你写:
template <typename T> struct B {};
然后它可以与A<int, int>
或C<3>
或甚至普通D
一起使用。
虽然可以使用模板模板参数,但这通常是一个坏主意。您应该将类的模板参数视为实现细节并应用黄金法则:不要依赖于实现细节。
如果您需要以某种方式访问该类型,请使用关联类型(又名T::AssociatedType
)或特征(BTraits<T>::AssociatedType
)
编辑:处理模板模板参数的多个实例化。
假设我们想要“擦除”这样一个类的模板模板参数:
template <template <typename> class A>
struct Something {
template <typename T>
void doit() { A<T>::doit(); }
};
C ++标准分配模型是使用内部rebind
结构:
template <typename T>
struct Simple {
template <typename U>
struct rebind { typedef Simple<U> type; };
};
template <typename T0, typename T1>
struct Multi {
template <typename U>
struct rebind { typedef Multi<U, T1> type; };
};
template <typename A>
struct Something {
template <typename T>
void doit() { typedef typename A::rebind<T>::type B; B::doit(); }
};
请注意如何在rebind
中使用复杂的计算,并且没有任何东西强迫您盲目地传递作为参数接收的类型。
虽然另一个(类似的)解决方案是要求工厂(也就是说,传递的对象本身不能使用,但它可以构建有用的对象);为了便于使用,C ++容器询问它们的分配器,它们既可以用于自己,也可以用于其他类型的工厂。
答案 2 :(得分:1)