1

我一直在阅读有效的现代 C++ 并且以下内容引起了我的注意:

在第 28 条中,斯科特写道:

总之,这些关于通用引用和左值/右值编码的观察意味着对于这个模板

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

推导的模板参数 T 将编码传递给 param 的参数是左值还是右值。编码机制很简单。当左值作为参数传递时,T 被推断为左值引用。当传递一个右值时,T 被推断为非引用。(注意不对称:左值被编码为左值引用,而右值被编码为非引用。)

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

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

4

2 回答 2

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

于 2015-08-29T10:25:09.970 回答
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通过右值传入,我们需要取得所有权 -T是一个非引用类型,所以我们最终移动构造 into s

T我可以在这里用作store, 而不是的模板参数这一事实std::conditional_t<std::is_lvalue_reference<T>::value, T, std::remove_reference_t<T>>可能不是偶然的。

于 2015-08-29T09:35:18.973 回答