web-dev-qa-db-ja.com

`const`を追加すると、ユニバーサル参照が右辺値になる理由

スコットの最後の傑作であるc ++ 11と14に関するユニバーサル参照について読んでいますが、左辺値または右辺値タイプの参照パラメーターのいずれかに引数が割り当てられているにもかかわらず、ユニバーサル参照と呼ばれるものの間に何かがあります。渡された引数の型特性に基づくl/rvalue。パラメータがユニバーサル参照になる理由は理解できましたが、はっきりしないのは、型パラメータにconstを追加する理由ですconst T&& p pを右辺値にする:

template<typename T>
void f(T&& param); // param is an universal reference

template<typename T>
void f(const T&& param); // param is an rvalue reference

constは、参照パラメーターに割り当てられたときにこれ以上のことを行いますか?.

24
RaGa__M

正式名称は普遍的な参照ではありませんが、 転送参照 です。 Standard は、cv-unqualifiedテンプレートパラメータへの右辺値参照のみがこのカテゴリに分類されることを示しています。

14.8.2.1関数呼び出しからテンプレート引数を推測する[temp.deduct.call]

3 Pがcv修飾型である場合、Pの型の最上位のcv修飾子は型推定のために無視されます。 Pが参照型の場合、Pによって参照される型が型の推定に使用されます。 転送参照は、cv非修飾テンプレートパラメータへの右辺値参照です。Pが転送参照であり、引数が左辺値の場合、タイプ「Aへの左辺値参照」が使用されます。タイプ控除のAの代わりに。 [例:

template <class T> int f(T&& heisenreference);
template <class T> int g(const T&&);
int i;
int n1 = f(i); // calls f<int&>(int&)
int n2 = f(0); // calls f<int>(int&&)
int n3 = g(i); // error: would call g<int>(const int&&), which
               // would bind an rvalue reference to an lvalue

—終了例]

const T&&が転送参照として動作できるようにすると、パラメータとして右辺値参照のみを受け取るテンプレート関数をオーバーロードできなくなります。

更新:@ HowardHinnantがコメントで言及しているように、const T&&には用途があります( このQ&A )。

18
TemplateRex