我一直在阅读Effective Modern C ++,以下内容引起了我的注意:
在第28项中斯科特写道:
这些关于普遍参考和观点的观察 左值/右值编码表示该模板
template<typename T> void func(T&& param);
推导出的模板参数T将进行编码 传递给param的参数是左值还是左值。该 编码机制很简单。当左值作为参数传递时, T被推断为左值参考。当rvalue通过时,T为 推断为不参考。 (注意不对称性:左值是 编码为左值引用,但rvalues编码为 非引用。)
有人可以解释为什么选择这种编码机制吗?
我的意思是,如果我们将遵循参考折叠规则而不是使用上述模板,则rvalue会产生右值参考。而且据我所知,如果它被推导为右值参考,那么一切都会起作用。为什么它被编码为非参考?
答案 0 :(得分:0)
假设您需要通过param
。实际上,您需要将其存储以用于终身目的。按原样,您只需使用T
:
template <typename T>
struct store { T val; };
template<typename T> void func(T&& param) {
store<T> s{std::forward<T>(param)};
}
这是有效的,因为如果param
被左值传入,T
将是左值引用类型,我们只是复制引用。如果param
被rvalue传入,我们需要获得所有权 - T
是非参考类型,因此我们最终将移动构建到s
。
我可以在这里使用T
作为store
的模板参数,而不是std::conditional_t<std::is_lvalue_reference<T>::value, T, std::remove_reference_t<T>>
,这可能不是偶然的。
答案 1 :(得分:0)
我认为你在想错误的方法。而不是问“为什么不总是使T
成为引用类型”,而是从另一方面看:
假设您有template <typename T> void f(T&&t)
。
将其称为int i; f(i);
,需要一些T
,以便T&&
解析为int&
。什么是最简单的T
可以实现的目标?它是int&
。
将其称为f(0);
,需要一些T
,以便T&&
解析为int&&
。什么是最简单的T
可以实现的目标?它是int
,而不是int&&
。
int&&
在这里根本没有任何优势。