关于《Effective Modern C++》模板类型推导Case1右值引用的疑问
如何在模板类型推导Case1中写出右值引用而非万能引用?
核心区别:Case1 vs 万能引用(Case2)
Scott Meyers在《Effective Modern C++》Item1中定义的Case1,核心是ParamType是明确的引用/指针类型(左值或右值),且不依赖模板参数的T&&形式;而万能引用(Case2)必须满足两个条件:
- 函数参数类型是
T&& T是正在被推导的函数模板参数
你写出的template<typename T> void f(T&& param);刚好命中万能引用的条件,所以属于Case2,而非Case1。
如何写出Case1的右值引用示例
要在模板类型推导的Case1中展示右值引用,只需要让ParamType成为明确的右值引用类型,而非直接的T&&。比如:
- 直接指定参数为具体类型的右值引用(如果是模板函数,可让模板参数用于其他逻辑,而非参数类型的
&&部分) - 让参数类型是基于模板参数的嵌套类型的右值引用
举个典型的示例:
#include <vector> // Case1场景:ParamType是std::vector<T>&&(明确的右值引用),不是万能引用 template<typename T> void f(std::vector<T>&& param) { // param只能接收std::vector<T>类型的右值 } int main() { std::vector<int> vec{1,2,3}; // f(vec); // 编译错误:左值无法绑定到右值引用,符合Case1的规则 f(std::move(vec)); // 合法:std::move将左值转为右值 f(std::vector<int>{4,5,6}); // 合法:临时对象是右值 }
这个例子里,模板参数T是vector的元素类型,而函数参数是std::vector<T>&&——这是明确的右值引用,不属于万能引用。此时类型推导规则和Case1的左值引用完全一致:
- 取实参的类型(比如
std::vector<int>),去掉引用属性(还是std::vector<int>) - 推导模板参数
T为int - 最终ParamType的类型是
std::vector<int>&&
同时也符合Case1中“仅右值实参可传递给右值引用参数”的规则。
关联Case2右值实参的子情况理解
完全可以把Case2中实参为右值的场景,和Case1的右值引用规则关联起来:
- 当万能引用(Case2)接收右值实参时,模板参数
T会被推导为非引用类型,此时T&&会折叠为右值引用(比如实参是int右值,T推导为int,T&&就是int&&) - 这种情况下,万能引用的行为和Case1的右值引用完全一致——只能接受右值,参数类型是右值引用
- 但本质区别在于:万能引用还能接收左值实参(此时
T推导为左值引用,T&&折叠为左值引用),而Case1的右值引用只能接收右值,是固定的引用类型。
内容的提问来源于stack exchange,提问作者Dhwani Katagade
相关产品推荐
相关产品推荐

