为什么不转发引用const?

beg*_*ses 5 c++ c++11 forwarding-reference

转发参考应该将参数转发给另一个函数,对吗?那么为什么它不是const?

template <typename T>
void func(const T&&);
Run Code Online (Sandbox Code Playgroud)

非常量引用允许函数修改其参数(而不是仅转发参数)。

eer*_*ika 9

为什么不转发引用const?

因为希望能够移动完美转发的xvalue。通常无法从const引用中移动对象,因为move构造函数的参数需要为非const。

此外,希望能够将左值绑定到转发引用中。不能将左const T&&值绑定为常量右值引用-根本不是转发引用1

如果您不想离开该参数,而只是不断引用它,那么就不需要转发参考。在那种情况下,一个常量值引用就足够了。

例:

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
Run Code Online (Sandbox Code Playgroud)

在这里,我们希望bararg移入fooarg情况2和3,并希望在情况1中复制它。转发参考可以达到此目的。const rvalue引用没有,因为不可能将const引用传递给move构造函数。


常量右值引用很少有用。标准库在一些地方使用它们:

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;
Run Code Online (Sandbox Code Playgroud)

这些已删除的重载旨在防止使用临时参数(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;
Run Code Online (Sandbox Code Playgroud)

上面,在访问包装后的值时,将const rvalue引用用作包装的返回类型,以便保持包装后的值的值类别和常数。


1个标准(草稿)说:

[temp.deduct.call] ...转发引用是对cv不合格模板参数的右值引用,该参数不代表类模板的模板参数(在类模板参数推导期间[[over.match.class.deduct ]))。如果P是转发引用,并且参数是左值,则使用类型“对A的左值引用”代替A进行类型推导。

  • @alfC是的,`ref(const T &amp;&amp;)= delete`禁止从临时(即右值)构造。如果它是re​​f(T &amp;&amp; = delete),那么它将阻止所有使用,因为转发参考绑定到任何东西。 (2认同)