Upload
mooopan
View
127
Download
0
Embed Size (px)
Citation preview
Effective Modern C++ Item 24: Distinguish universal references from
rvalue references.
@mooopan
自己紹介
• 藤田康博(@mooopan)
• 株式会社Preferred Networks エンジニア
• C++でゲームのAIを書いたり機械学習したり
Item 24: Distinguish universal references from rvalue references.
• “T&&”(Tは型)は文脈によって2つの意味を持つ
• Rvalue reference
• Universal reference
• この2つを区別できるようになろう!
Rvalue reference• 右辺値にのみ束縛される
// no errorint&& x = 0;
int a = 0;// error: cannot bind 'int' lvalue to 'int&&'int&& y = a;
Universal reference• 右辺値にも左辺値にも束縛される auto&& x = 0; // no error
int a = 0;auto&& y = a; // no error
• (const/non-const,volatile/non-volatile関係なくなんにでも束縛される→universal)
Universal referenceの働き• lvalueで初期化するとlvalue referenceに,rvalueで初期化するとrvalue referenceになる
// param is a universal referencetemplate<typename T>void f(T&& param);Widget w;// param's type is Widget&, an lvalue referencef(w); // param's type is Widget&&, an rvalue referencef(std::move(w));
Universal referenceが 現れる2つの文脈
• テンプレートパラメータ // param is a universal referencetemplate<typename T>void f(T&& param);
• auto宣言 // x is a universal referenceint a = 0;auto&& x = a;
• 共通点:型推論の存在
Universal referenceでない例
• “T&&”の形をしていても型推論が起こらなければuniversal referenceではない
// no type deduction;// param is an rvalue referencevoid f(Widget&& param);
// no type deduction;// param is an rvalue referenceWidget&& var1 = Widget();
見分け方
• もし変数やパラメータの型宣言が正確に“T&&”(ただしTは推論される型)という形なら,それはuniversal reference.
紛らわしい例 (1)• 正確に “T&&”の形になっている必要がある // param is an rvalue referencetemplate<typename T>void f(std::vector<T>&& param);
// param is an rvalue referencetemplate<typename T>void f(const T&& param);
紛らわしい例 (2)• テンプレートを使っていて正確に“T&&”の形になっていてもuniversal referenceではない場合がある
template<class T, class Allocator = allocator<T>>class vector {public: // x is an rvalue reference void push_back(T&& x);};
• Tはvectorの実体化の際に決まり,push_backで型推論は起こらない
紛らわしい例 (3)• Variadic templateのtemplate parameter packもuniversal referenceになりうる
template<class T, class Allocator = allocator<T>>class vector {public: // args are zero or more universal references template <class... Args> void emplace_back(Args&&... args);};
紛らわしい例 (4)
• Generic lambdaの引数ではauto&&の形をとる // func is a universal reference// params are zero or more universal referencesauto timeFuncInvocation = [](auto&& func, auto&&... params) {...};
ここまで全部嘘
• Universal referenceという種類の参照があるわけではない
• 実際に起こっているのはreference collapsing(Item 30で扱う)
• しかし便利な概念なので後の章でも使う
まとめ• 関数テンプレートパラメータの型が“T&&”(Tは推論される型)だったりオブジェクトがauto&&を使って宣言されたりしたら,それはuniversal reference.
• 正確に“T&&”の形になっていなかったりTの型推論が起こらない場合はただのrvalue reference.
• Universal referenceはrvalueで初期化されればrvalue referenceに対応するしlvalueで初期化されればlvalue referenceに対応する