转发参考应该将参数转发给另一个函数,对吗?那为什么不常量呢?
template <typename T>
void func(const T&&);
非常量引用允许函数修改其参数(而不仅仅是转发参数)。
答案 0 :(得分:9)
为什么不转发参考常量?
因为希望能够移动一个完美转发的xvalue。通常,不能从const引用中移动对象,因为move构造函数的参数必须为非const。
此外,希望能够将左值绑定到转发引用中。不可能将左值绑定到作为常量右值引用的const T&&
中-根本不是 1 的转发引用。
如果您不想离开该参数,而只是不断地引用它,那么就不需要转发引用。在这种情况下,const左值引用就足够了。
示例:
struct S {
S() = default;
S(S&&) = default; // move
S(const S&) = default; // copy
};
void foo(S fooarg);
template <typename T>
void bar(T&& bararg) { // forwarding reference
foo(std::forward<T>(bararg));
}
// call site
S s;
bar(s); // 1 copy
bar(S{}); // 2 move
bar(std::move(s)); // 3 move
在这里,我们希望在情况2和3中将bararg
移到fooarg
中,并希望在情况1中将其复制。转发参考可以实现这一点。不能使用const rvalue引用,因为无法将const引用传递给move构造函数。
常量右值引用很少有用。标准库在few places中使用它们:
template <class T> void as_const(const T&&) = delete;
template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;
这些已删除的重载旨在防止使用临时参数(rvalue)调用函数。 const
阻止参数成为转发引用,该引用将绑定到任何内容,因此删除所有呼叫。
constexpr const T&& optional::operator*() const&&;
constexpr const T&& optional::value() const &&;
template <class T, class... Types>
constexpr const T&& get(const std::variant<Types...>&& v);
template< class T, class... Types >
constexpr const T&& get(const tuple<Types...>&& t) noexcept;
以上,在访问包装后的值时,将const rvalue引用用作包装的返回类型,以便保持包装后的值的值类别和常数。
1 标准(草稿)说:
[temp.deduct.call] ...转发引用是对 cv不合格模板参数的右值引用,该参数不表示类模板的模板参数(在类模板参数期间)扣除([over.match.class.deduct]))。 如果P是转发引用,并且参数是左值,则使用类型“对A的左值引用”代替A进行类型推导。