15
Effective Modern C++ Item 24: Distinguish universal references from rvalue references. @mooopan

Effective Modern C++ Item 24: Distinguish universal references from rvalue references

  • Upload
    mooopan

  • View
    127

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

Effective Modern C++ Item 24: Distinguish universal references from

rvalue references.

@mooopan

Page 2: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

自己紹介

• 藤田康博(@mooopan)

• 株式会社Preferred Networks エンジニア

• C++でゲームのAIを書いたり機械学習したり

Page 3: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

Item 24: Distinguish universal references from rvalue references.

• “T&&”(Tは型)は文脈によって2つの意味を持つ

• Rvalue reference

• Universal reference

• この2つを区別できるようになろう!

Page 4: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

Rvalue reference• 右辺値にのみ束縛される

// no errorint&& x = 0;

int a = 0;// error: cannot bind 'int' lvalue to 'int&&'int&& y = a;

Page 5: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

Universal reference• 右辺値にも左辺値にも束縛される auto&& x = 0; // no error

int a = 0;auto&& y = a; // no error

• (const/non-const,volatile/non-volatile関係なくなんにでも束縛される→universal)

Page 6: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

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));

Page 7: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

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;

• 共通点:型推論の存在

Page 8: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

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();

Page 9: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

見分け方

• もし変数やパラメータの型宣言が正確に“T&&”(ただしTは推論される型)という形なら,それはuniversal reference.

Page 10: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

紛らわしい例 (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);

Page 11: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

紛らわしい例 (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で型推論は起こらない

Page 12: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

紛らわしい例 (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);};

Page 13: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

紛らわしい例 (4)

• Generic lambdaの引数ではauto&&の形をとる // func is a universal reference// params are zero or more universal referencesauto timeFuncInvocation = [](auto&& func, auto&&... params) {...};

Page 14: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

ここまで全部嘘

• Universal referenceという種類の参照があるわけではない

• 実際に起こっているのはreference collapsing(Item 30で扱う)

• しかし便利な概念なので後の章でも使う

Page 15: Effective Modern C++ Item 24: Distinguish universal references from rvalue references

まとめ• 関数テンプレートパラメータの型が“T&&”(Tは推論される型)だったりオブジェクトがauto&&を使って宣言されたりしたら,それはuniversal reference.

• 正確に“T&&”の形になっていなかったりTの型推論が起こらない場合はただのrvalue reference.

• Universal referenceはrvalueで初期化されればrvalue referenceに対応するしlvalueで初期化されればlvalue referenceに対応する