了解完美转发和可变参数模板的片段

pur*_*dox -1 c++ templates typedef variadic-templates perfect-forwarding

我从这个答案中看到了这段代码的片段,我似乎无法理解模板和类型名的排列如何创建main()中显示的最终函数调用.

特别是,可变参数模板模板的安排和std :: forward的使用让我很困惑.

任何人都可以打破这段代码,以便我能更好地理解它吗?

#include <utility>

template <template <typename...> class TemplateClass, typename... Args>
TemplateClass<Args...> make(Args&&... args)
{
    return TemplateClass<Args...>(std::forward<Args>(args)...);
}

int main() 
{
  make<std::pair>(1, 2);
}
Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激.

dyp*_*dyp 7

这是一个带有模板模板参数的函数模板:

template <template <typename, typename> class TT>
TT<int, double>
make(int i, double d)
{
    return TT<int, double>(i, d);
}
Run Code Online (Sandbox Code Playgroud)

您指定了一个具有两个类型参数的类或别名模板,此函数将使用此模板的特化,使用intdouble作为模板参数创建.例如:

make< std::pair >(42, 4.2);
Run Code Online (Sandbox Code Playgroud)

这会返回一个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);
}
Run Code Online (Sandbox Code Playgroud)

模板参数Arg0Arg1旨在被从类型的用来调用所述功能的(函数)的参数推导出:

int i = 42;
double d = 4.2;
make< std::pair >(i, d); // returns a `std::pair<int, double>`
Run Code Online (Sandbox Code Playgroud)

对于更复杂的数据类型,我们可能希望使用完美转发:

make< std::pair >( 42, std::vector<int>(1000) );
Run Code Online (Sandbox Code Playgroud)

这会返回一个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));
}
Run Code Online (Sandbox Code Playgroud)

通过创建的临时向量std::vector<int>(1000)将移动到return语句中创建的对象中.


现在,我们可以将这个函数模板推广到N个参数; 模板template-parameter也必须进行通用化,以便您可以传递任何带有一些类型参数的类或别名模板.

template <template <typename...> class TemplateClass, typename... Args>
TemplateClass<Args...> make(Args&&... args)
{
    return TemplateClass<Args...>(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)