次の点を考慮してください。
struct my_type {};
my_type make_my_type() { return my_type{}; }
void func(my_type&& arg) {}
int main()
{
my_type&& ref = make_my_type();
func(ref);
}
言うまでもなく、このコードはコンパイルされません。2 番目の関数呼び出しで使用する必要があることstd::move()
は理解していますが、理解のためにコードをそのまま考えたいと思います。
上記をコンパイルしようとすると、Clang 3.5 から次のように表示されます。
エラー: 'func' の呼び出しに一致する関数がありません
注: 候補関数は実行できません: 第 1 引数の「my_type」から「my_type &&」への既知の変換はありません void func(my_type&&) {}
g++ 4.9 はほぼ同じことを言っていますが:
エラー: 'my_type' 左辺値を 'my_type&&' にバインドできません
注: 'void func(my_type&&)' の引数 1 を初期化しています
これらのエラー メッセージは、かなり混乱しています。なぜなら、ref
は確かにlvalueですが、その型はまだmy_type&&
... ですよね?
私はここで何が起こっているのかを正確に理解しようとしているので、次のうちどれが (もしあれば) 正しいのか疑問に思っています:
右辺値参照にバインドできるのは右辺値のみで
ref
あり、左辺値であるため、 にバインドすることはできませんarg
。Clang と g++ の両方からのエラー メッセージは、それが「変換できない」ref
(非参照)であると主張することで誤解を招きます。my_type
これは左辺値であるため、実際の型が であるにもかかわらず、
ref
オーバーロード解決の目的で非参照として扱われます。Clang および g++ からのエラー メッセージは、実際の.my_type
my_type&&
ref
の本体では、明示的に と書いたにもかかわらず、
main()
の型ref
はプレーンです。したがって、コンパイラからのエラー メッセージは正確であり、私の予想は間違っています。ただし、これは当てはまらないようです。my_type
my_type&&
static_assert(std::is_same<decltype(ref), my_type&&>::value, "");
通過します。
私が考慮していない他の魔法が進行中です。
繰り返しますが、解決策はstd::move()
rref を右辺値に変換するために使用することです。「舞台裏」で何が起こっているのかの説明を探しています。