C++ 可变模板参数包转发中的语法差异

C++ 可变模板参数包转发中的语法差异,c++,c++11,variadic-templates,perfect-forwarding,C++,C++11,Variadic Templates,Perfect Forwarding,在使用可变模板时,我遇到了两种不同的方法来编写对std::forward的调用,但我想知道这两种语法之间的实际区别是什么 template<typename... T> void one(T&&... args) { foo(std::forward<T&&...>(args...)); } template<typename... T> void two(T&&... args) { foo(s

在使用可变模板时,我遇到了两种不同的方法来编写对
std::forward
的调用,但我想知道这两种语法之间的实际区别是什么

template<typename... T>
void one(T&&... args)
{
    foo(std::forward<T&&...>(args...));
}
template<typename... T>
void two(T&&... args)
{
    foo(std::forward<T&&>(args)...);
}
模板
无效一(T&…参数)
{
foo(std::forward(args…);
}
模板
无效二(T&…参数)
{
foo(std::forward(args)…);
}
根据我的编译器,这些都是有效的语法,在大多数情况下,编译器不会抱怨。但我发现有些情况下,其中一个或另一个是正确的,但编译器没有详细说明原因

一个比另一个正确吗?

它们有不同的用途吗?

..
位置告诉编译器在哪里展开包,在它前面的每一个元素上展开一次(很难表达,但我将在下面进行说明)

让我们考虑一个包<代码> t= {int,双,char }<代码>和<代码> ARGs= { 1,2,‘3’}< <代码> < /p> 您的第一个示例(

one
)将在
内部展开
T
,然后在
()
内部展开
args
,使其成为

foo(std::forward<T&&...>(args...));  // becomes:
foo(std::forward<int&&, double&&, char&&>(1, 2.0, '3'));
foo(std::forward<T&&>(args)...);  // becomes:
foo(std::forward<int&&>(1), std::forward<double&&>(2.0),std::forward<char&&>('3'));

至于为什么这两个参数都编译得很好,如果只使用一个参数调用,结果是相同的。如果你从来没有调用过它,那么它就不会被实例化。

第一个是错误的,除了一个元素包之外,它实际上不会编译。它被称为包扩展,因为它就是这样。用
one(2,2.3,2.3f)调用第一个示例将使函数体
foo(std::forward(2,2.3,2.3f)
无法编译。