Scott Meyers在此示例中足够清楚了RVALUE参考和转发参考之间的区别:
Widget&& var1 = someWidget; // here, “&&” means rvalue reference (1)
auto&& var2 = var1; // here, “&&” does not mean rvalue reference (2)
template<typename T>
void f(std::vector<T>&& param); // here, “&&” means rvalue reference (3)
template<typename T>
void f(T&& param); // here, “&&”does not mean rvalue reference (4)
本质上,当我们拥有可分解上下文时,这种区别发生在情况下,因此(3)明确指出我们具有vector<...>&&
,而将T
进行(4),并且在应用参考后进行(4)折叠规则)按"价值类别"分类。
但是,匹配更复杂的模式会发生什么?以以下情况为例:
template <template <class...> class Tuple, class... Ts>
void f(Tuple<Ts...>&& arg)
{
}
&&
在这里意味着什么?
在您的上一个示例中, arg
是rvalue参考。
a 转发参考是对CV UNqualified模板参数
的RVALUE参考
和Tuple<Ts...>
不是模板参数。
(引用[temp.deduct.call]。)
它是rvalue参考,而不是转发参考。
最简单的方法是尝试通过lvalue,如果失败,则是rvalue参考,如果不是,则转发参考:
template<typename... Ts>
struct foo {};
//f function definition
int main() {
foo<int, double> bar;
f(bar); // fails! Cannot bind lvalue to rvalue reference
f(foo<int, double>{}); // ok, rvalue is passed
}
概念转发引用不是标准概念,当您看到它时,它很有用,但是如果您想正确理解和处理它,则必须了解参考算术。(我相信迈耶的书也有一章)
转发参考概念背后的是参考算术:
- &amp;&amp;&amp;&amp;=&amp;&amp;
- &amp;&amp;&amp;=&amp;
- &amp;&amp;&amp;=&amp;
- &amp;&amp;=&amp;
让我们模拟使用转发参考的编译器模板类型扣除
template<class T>
void foo(T&&);
//...
const int i=42;
foo(i); // the compiler will defines T = const int &
// T&& = const int & && = const int &
// => the compiler instantiates void foo<const int &>(const int &);
foo(6*7);// the compiler will defines T = int
// T&& = int &&
// the compiler instantiates void foo<int>(int &&);
在这种情况下,模板的实例化可以产生函数wich通过lvalue参考或获取参数的函数rvalue参考参考:转发参考是根据模板类型扣除,rVALUE参考或LVALUE参考。它是这样命名的,因为在这种情况下,该参数应作为lvalue或xvalue传递,这是T&& std::forward<T>(T&& a)
如果您声明函数具有:
template<class T>
void foo(ATemplateClass<T> && a);
编译器推导的T类型是什么,您都将获得RVALUE参考Paramater。