プログラミング言語C++の関数型(function type)には左辺値(lvalue)しか存在しないが(→id:yohhoy:20200530)、左辺値参照型(R (&)(Args...)
)/右辺値参照型(R (&&)(Args...)
)いずれにも束縛できる。そう、よかったね。
#include <utility> using std::move; // 右辺値参照型(T&&)を返す関数 void f() {} // 関数型void() void ( &lref1)() = f; // OK void (&&rref1)() = f; // OK: 右辺値参照型だがlvalue束縛可能 void ( &lref2)() = move(f); // OK: 関数型の式move(f)はlvalue void (&&rref2)() = move(f); // OK: 右辺値参照型だがlvalue束縛可能 // (関数型のprvalueは存在しない) int n = 42; // 通常の型(int) int& lref3 = i; // OK int&& rref3 = i; // NG: 右辺値参照型はlvalue束縛不可 int& lref4 = move(i); // NG: 左辺値参照型はxvalue束縛不可 int&& rref4 = move(i); // OK int& lref5 = 42; // NG: 左辺値参照型はprvalue束縛不可 int&& rref5 = 42; // OK
関数オーバーロード解決では関数型への左辺値参照型が優先されるため、あいまいさは存在しない。(C++17 16.3.3.2/p3)
C++17 11.6.3/p5より一部引用(下線部は強調)。
A reference to type "cv1
T1
" is initialized by an expression of type "cv2T2
" as follows:
- If the reference is an lvalue reference and the initializer expression
- is an lvalue (but is not a bit-field), and "cv1
T1
" is reference-compatible with "cv2T2
", or- (snip)
- Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be
const
), or the reference shall be an rvalue reference. (snip)
- If the initializer expression
- is an rvalue (but not a bit-field) or function lvalue and "cv1
T1
" is reference-compatible with "cv2T2
", or- (snip)