这是一个带有模板模板参数的函数模板:
template <template <typename, typename> class TT>
TT<int, double>
make(int i, double d)
{
return TT<int, double>(i, d);
}
您指定一个具有两个类型参数的类或别名模板,并且此函数将使用此模板的特化,使用int
和double
作为模板参数创建。例如:
make< std::pair >(42, 4.2);
这会返回一个std::pair<int, double>
.
我们现在可以“模板化”这个函数的(函数)参数:
template <template <typename, typename> class TT, typename Arg0, typename Arg1>
TT<Arg0, Arg1>
make(Arg0 a0, Arg1 a1)
{
return TT<A0, A1>(a0, a1);
}
模板参数Arg0
和Arg1
旨在从用于调用函数的(函数)参数的类型中推导出来:
int i = 42;
double d = 4.2;
make< std::pair >(i, d); // returns a `std::pair<int, double>`
对于更复杂的数据类型,我们可能希望使用完美转发:
make< std::pair >( 42, std::vector<int>(1000) );
这会返回一个std::pair<int, std::vector<int>>
. 上面的定义make
将通过创建的临时向量移动std::vector<int>(1000)
到第二个函数参数中。但是,它将从那里复制TT<A0, A1>(a0, a1)
到通过创建的对象中。
我们可以改变 的定义make
来实现完美转发,如下所示:
template <template <typename, typename> class TT, typename Arg0, typename Arg1>
TT<Arg0, Arg1>
make(Arg0&& a0, Arg1&& a1)
{
return TT<A0, A1>(std::forward<A0>(a0), std::forward<A1>(a1));
}
通过创建的临时向量std::vector<int>(1000)
将被移动到在返回语句中创建的对象中。
现在,我们可以将这个函数模板泛化为 N 个参数;模板模板参数也必须通用化,以便您可以传递任何带有一定数量类型参数的类或别名模板。
template <template <typename...> class TemplateClass, typename... Args>
TemplateClass<Args...> make(Args&&... args)
{
return TemplateClass<Args...>(std::forward<Args>(args)...);
}