转发引用:引用参数来源
Forwarding references: reference parameter origin
关于转发引用(又名通用引用)的整个前提是,这个函数:
template<typename T>
void f(T&&) { }
可能导致模板参数为 int&
或 int
,具体取决于您是以 int a{}; f(a)
还是 f(5)
为例调用它。但我认为这已经太过分了。因为当我有一个像
这样的函数时
template<typename T>
auto g(T) -> void {}
然后它总是将模板参数解析为 int
,无论我如何调用它。而且尽管 auto h(int&) -> void {}
是完全合法的。
那么有什么规则允许 f
的模板参数作为参考,而不是 g
的模板参数?
对于函数参数具有 T&&
(cv-unqualified)形式的情况,模板参数推导规则中有一个特定的例外,其中 T
是模板参数。这种特殊情况如被称为 转发参考.
的问题所示
对于转发引用,如果函数参数是左值,则为 T
推导左值引用,而通常不会推导任何引用类型。
您可以通过尝试使用例如const T&&
而不是 T&&
,特殊规则不适用。在任何情况下,它都会为 T
推断出非引用类型,尽管函数调用可能无法进行。
你可以阅读 Effective modern C++ 的答案,第一章,它说,我们可以认为函数模板看起来像这样:
template<typename T>
void f(paramType param);
T
和 paramType
通常不同,paramType 通常包含像 const 这样的修饰符或像 const T&
这样的引用限定符
他在三个案例中谈到了这一点
- paramType 是指针或引用类型
- paramType 是通用引用
- paramType 既不是指针也不是引用
你的第一个函数是case2,因为需要推导类型,&&
这里是通用引用,你的第二个函数是case3,paramType既不是指针也不是引用
During type deduction for a template parameter that is a universal
reference, lvalues and rvalues of the same type are deduced to have
slightly different types.
- 类型 T 的左值被推导为类型 T&
- 类型 T 的右值被推导为类型 T
所以f(a)
你得到了f(int& && param)
然后是“引用折叠”规则
- 右值引用到右值引用成为右值引用
- 对引用的所有其他引用都折叠成左值引用
所以你得到了f(int& param)
关于转发引用(又名通用引用)的整个前提是,这个函数:
template<typename T>
void f(T&&) { }
可能导致模板参数为 int&
或 int
,具体取决于您是以 int a{}; f(a)
还是 f(5)
为例调用它。但我认为这已经太过分了。因为当我有一个像
template<typename T>
auto g(T) -> void {}
然后它总是将模板参数解析为 int
,无论我如何调用它。而且尽管 auto h(int&) -> void {}
是完全合法的。
那么有什么规则允许 f
的模板参数作为参考,而不是 g
的模板参数?
对于函数参数具有 T&&
(cv-unqualified)形式的情况,模板参数推导规则中有一个特定的例外,其中 T
是模板参数。这种特殊情况如被称为 转发参考.
对于转发引用,如果函数参数是左值,则为 T
推导左值引用,而通常不会推导任何引用类型。
您可以通过尝试使用例如const T&&
而不是 T&&
,特殊规则不适用。在任何情况下,它都会为 T
推断出非引用类型,尽管函数调用可能无法进行。
你可以阅读 Effective modern C++ 的答案,第一章,它说,我们可以认为函数模板看起来像这样:
template<typename T>
void f(paramType param);
T
和 paramType
通常不同,paramType 通常包含像 const 这样的修饰符或像 const T&
他在三个案例中谈到了这一点
- paramType 是指针或引用类型
- paramType 是通用引用
- paramType 既不是指针也不是引用
你的第一个函数是case2,因为需要推导类型,&&
这里是通用引用,你的第二个函数是case3,paramType既不是指针也不是引用
During type deduction for a template parameter that is a universal reference, lvalues and rvalues of the same type are deduced to have slightly different types.
- 类型 T 的左值被推导为类型 T&
- 类型 T 的右值被推导为类型 T
所以f(a)
你得到了f(int& && param)
然后是“引用折叠”规则
- 右值引用到右值引用成为右值引用
- 对引用的所有其他引用都折叠成左值引用
所以你得到了f(int& param)