Lvalue / rvalue -nes编码用于通用引用

时间:2015-08-29 09:28:14

标签: c++ language-lawyer lvalue rvalue universal-reference

我一直在阅读Effective Modern C ++,以下内容引起了我的注意:

在第28项中斯科特写道:

  

这些关于普遍参考和观点的观察   左值/右值编码表示该模板

     

template<typename T> void func(T&& param);

     

推导出的模板参数T将进行编码   传递给param的参数是左值还是左值。该   编码机制很简单。当左值作为参数传递时,   T被推断为左值参考。当rvalue通过时,T为   推断为不参考。 (注意不对称性:左值是   编码为左值引用,但rvalues编码为   非引用。)

有人可以解释为什么选择这种编码机制吗?

我的意思是,如果我们将遵循参考折叠规则而不是使用上述模板,则rvalue会产生右值参考。而且据我所知,如果它被推导为右值参考,那么一切都会起作用。为什么它被编码为非参考?

2 个答案:

答案 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&&在这里根本没有任何优势。