Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

C++14言語編

1.092 Aufrufe

Veröffentlicht am

C++17 が出たので C++14 の復習(と言う名の学習)をしました。
ebisu_feature.cpp で使用したスライドです。

Veröffentlicht in: Software
  • Loggen Sie sich ein, um Kommentare anzuzeigen.

C++14言語編

  1. 1. C++14 すごーい! たーのしー!!! 言語編 2017/11/29 鳥頭かりやマン 1
  2. 2. 趣旨 C++17も出るので改めて C++14の復習をしよう! 2
  3. 3. 言い訳 C++14 全く分かってなかったので、 慌てて予習※してきました。間違い や不足がめっさあると思うので訂 正・補足よろしくお願いします。 ※ C++17出るって言うのにC++14予習とか(プゲラ 3
  4. 4. C++14 言語編 お題 2進リテラル 数値リテラルの桁区切り ラムダ式の初期化キャプチャ(汎用ラムダキャプチャ) ジェネリックラムダ 通常関数の戻り値型推論 後置戻り値型のプレースホルダ decltype(auto) 戻り値型推論の範囲拡大 ラムダ式の戻り値型推論の変更 サイズ付きデアロケーション 4
  5. 5. C++14 言語編 お題 constexpr関数の制限緩和 constexpr関数の暗黙のconst修飾廃止 変数テンプレート deprecated属性 メンバ初期化子と集成体初期化 初期化リストの中括弧省略可能範囲拡大 リテラル演算子定義時のスペース省略 std::nullptr_t型の非型テンプレートパラメータ 文脈依存変換の微調整 メモリアロケーションの明確化 5
  6. 6. C++14 言語編 お題 マイナーバージョンアップって一体… 6
  7. 7. 2進リテラル N3472 Binary Literals in the C++ Core Language http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3472.pdf 7
  8. 8. 2進リテラル C++ でもようやく2進数 のリテラルが使えるよう になりました。 8
  9. 9. 2進リテラル 9 導入の背景
  10. 10. 2進リテラル 導入の背景 10 アイツらは使えるのに何でオレ の言語では使えないんだ! (注)想像です。
  11. 11. 2進リテラル 導入の背景 11 アイツら⇒
  12. 12. 2進リテラル 書き方 12
  13. 13. 2進リテラル 書き方 0b か 0B を頭に付ける 16進:0x5b 2進:0b01011011 13
  14. 14. 2進リテラル 書き方 これで整数リテラルは以下の4種類に 0以外の数字で始まり、0文字以上の数字が続く:10進リテラル 0で始まり、0文字以上の8進の数字が続く:8進リテラル 0xで始まり、1文字以上の16進の数字が続く:16進リテラル 0bで始まり、1文字以上の2進の数字が続く:2進リテラル 14
  15. 15. 2進リテラル 書き方 余談 整数リテラルにマイナス記号は 許されない!!! つまり、マイナスのリテラルは存 在しない!!! 15
  16. 16. 2進リテラル 書き方 更に余談 0は8進リテラル!!! 16
  17. 17. 2進リテラル 接尾辞(suffix)と型 17
  18. 18. 2進リテラル 接尾辞と型 他の整数リテラルと 同様、U とか LL とか 使える 18
  19. 19. 2進リテラル 接尾辞と型 0b1000 : int 0b1000U : unsigned 0b1000L : long 0b1000LL: long long 19
  20. 20. 2進リテラル 接尾辞と型 小文字も使えるけど… 0b1000ll: long long 読めねぇ… 20
  21. 21. 2進リテラル 接尾辞と型 余談 ULL か LLU なら unsigned long long。 Ull、uLL、LLu、llU も OK。 lL、Ll は NG。 ※まぁ普通は全部大文字使いますよね?大文字使わない? 21
  22. 22. 2進リテラル 接尾辞と型 ユーザ定義リテラルでも使える。 例えば、chrono と組み合わせて、 0b10001000min、0b10100101ms 的な… 使うかな… (complexなら組み合わせて使いそう?) 22
  23. 23. 2進リテラル 接尾辞と型 2進リテラルの型は、8進リテラル、 16進リテラルと同様に決定され る。 10進リテラルとはちょっと違う… 23
  24. 24. 2進リテラル 接尾辞と型 接尾辞に U が無い場合 以下の中で値が最初に表せる型 int unsigned int long int unsigned long int long long int unsigned long long int unsigned 系があるの、地味にヤバい… (10進リテラルの場合は unsigned 系は無い) 24 LL付き L付き 何も 無し
  25. 25. 2進リテラル 接尾辞と型 接尾辞に U がある場合 以下の中で値が最初に表せる型 unsigned int unsigned long int unsigned long long int (U付きの場合は10進リテラルでも同じ) 25 ULL 付き UL付き U付き
  26. 26. 数値リテラルの桁区切り 26
  27. 27. 数値リテラルの桁区切り N2281 Digit Separators http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2281.html N3342 Digit Separators coming back http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3342.html N3448 Painless Digit Separation http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3448.pdf N3499 Digit Separators http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3499.html N3661 Digit Separators http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3661.html N3781 Single-Quotation-Mark as a Digit Separator http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3781.pdf 27
  28. 28. 数値リテラルの桁区切り 余談 たかだか数値リテラルに 桁区切り追加するためだ けにしてはペーパー数多 過ぎませんかね… 28
  29. 29. 数値リテラルの桁区切り C++ でもようやく数値リ テラルに区切り文字が 使えるようになりました。 でも区切り文字はシングルクォート 29
  30. 30. 数値リテラルの桁区切り 30 導入の背景
  31. 31. 数値リテラルの桁区切り 導入の背景 31 500000000000000 円欲しい!!! 読めねぇ…
  32. 32. 数値リテラルの桁区切り 導入の背景 32 500'000'000'000'000 円欲しい!!! 読める!(ホントか?) (あ、桁足りなかった…)
  33. 33. 数値リテラルの桁区切り 33 なぜ区切り文字が シングルクォート?
  34. 34. 数値リテラルの桁区切り なぜシングルクォート? 34 もともとの提案はアンダースコアだった。 でも、ユーザ定義リテラルと区別がつかなく なるのを避けるため、シングルクォートが提 案された。 ペーパーの例:0xdead_beef_db どっからがユーザ定義接尾辞?
  35. 35. 数値リテラルの桁区切り 35 区切り文字 挿入可能位置
  36. 36. 数値リテラルの桁区切り 区切り文字挿入可能位置 36 数字列の途中ならどこでも可能 ただし、最初と最後はダメ 連続もダメ OK:123'456、1'2'3'4'5、0x1'2345 0'755、0b1000'1101'0010 NG:'123、456'、0x'1234、123''456
  37. 37. 数値リテラルの桁区切り 区切り文字挿入可能位置 37 浮動小数点リテラルでも可能 何と、指数部でも可能 OK:1'234.567'89、1'234E+5、 1'234.567E+1'333、123E4'5'6 NG:123E+'456、123'E+456、 123E'456、123'.4、123.'4
  38. 38. 数値リテラルの桁区切り 38 後方互換性
  39. 39. 数値リテラルの桁区切り 後方互換性 39 各種シンタックス ハイライト破壊王 気持ちは分かる…
  40. 40. 数値リテラルの桁区切り 後方互換性 40 プリプロセッサが絡むと結果が今までと結果が異な る場合がある。(でちまるさん以外多分影響ない) 規格書の例(改) #define M(x, ...) __VA_ARGS__ int x[2] = { M(1'2,3'4,5) }; // int x[2] = { 5 }; — C++11 // int x[2] = { 3'4,5 }; — C++14
  41. 41. ラムダ式の初期化キャプ チャ(汎用ラムダキャプ チャ) N3610 Generic lambda-capture initializers, supporting capture-by-move http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3610.html N3648 Wording Changes for Generalized Lambda-capture http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3648.html 41
  42. 42. ラムダ式の初期化キャプ チャ 42 導入の背景
  43. 43. ラムダ式の初期化キャプ チャ 導入の背景 43 ラムダキャプ チャでもムー ブがしたい!
  44. 44. ラムダ式の初期化キャプ チャ 導入の背景 44 unique_ptr とかのコピーできない オブジェクトをキャプチャしたい。 コピーのコストが高価なオブジェ クトをキャプチャしたい。
  45. 45. ラムダ式の初期化キャプ チャ 45 書き方
  46. 46. ラムダ式の初期化キャプ チャ 書き方 46 [] の中で、変数名の後に初期化 子を書くだけ! auto f = [p = std::move(p)]() { ... };
  47. 47. ラムダ式の初期化キャプ チャ 書き方 47 直接初期化でもOK! auto f = [p{std::move(p)}]() { ... };
  48. 48. ラムダ式の初期化キャプ チャ 書き方 48 もちろん任意の数式が書ける! auto f = [p{a + b * 42}]() { ... };
  49. 49. ラムダ式の初期化キャプ チャ 49 なぜ&&じゃないのか why C++ people
  50. 50. ラムダ式の初期化キャプ チャ なぜ&&じゃないのか 50 実は2009年に日本から&&で ムーブキャプチャをしたいとの要 望があがっていたが、否決され た… http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2863.html#JP9
  51. 51. ラムダ式の初期化キャプ チャ なぜ&&じゃないのか 51 問題点1 && は普通右辺値参照に使う。 ⇓ ムーブしたいのであって、右辺値参 照の変数に束縛したいわけじゃな い。
  52. 52. ラムダ式の初期化キャプ チャ なぜ&&じゃないのか 52 問題点2 && の右に変数名を書くとムーブさ れる。 ⇓ 名前付きのオブジェクトをstd::move 無しでムーブするのは危険。
  53. 53. ジェネリックラムダ N3418 Proposal for Generic (Polymorphic) Lambda Expressions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3418.pdf N3559 Proposal for Generic (Polymorphic) Lambda Expressions (Revision 2) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3559.pdf N3649 Generic (Polymorphic) Lambda Expressions (Revision 3) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3649.html 53
  54. 54. ジェネリックラムダ 54 導入の背景
  55. 55. ジェネリックラムダ 導入の背景 55 ラムダ式で引数 の型書くのまん どくさい!!!
  56. 56. ジェネリックラムダ 導入の背景 56 ペーパーに記載されていた例 std::for_each(begin(v), end(v), [](decltype(*begin(v)) x) { std::cout << x; } ); auto get_size = [](std::unordered_multimap<std::wstring,std::list<std ::string> > const& m) { return m.size(); };
  57. 57. ジェネリックラムダ 57 書き方
  58. 58. ジェネリックラムダ 書き方 58 ラムダ式の引数の型にautoを 使うだけ!!!
  59. 59. ジェネリックラムダ 導入の背景 59 さっきの例に適用すると… std::for_each(begin(v), end(v), [](auto& x) { std::cout << x; } ); auto get_size = [](auto& m) { return m.size(); }; めっさスッキリ!!!
  60. 60. ジェネリックラムダ 60 auto の意味
  61. 61. ジェネリックラムダ auto の意味 61 それぞれのautoが別々のテン プレート型引数であるかのよ うに振る舞う
  62. 62. ジェネリックラムダ auto の意味 62 [](auto a, auto b) { return a + b; } ⇓ template<typename T, typename U> [](T a, U b) { return a + b; } ※こんな構文は実際にはありません。
  63. 63. ジェネリックラムダ auto の意味 63 素朴な疑問 ジェネリックラムダはテンプレー トなのに変数に代入できるの?
  64. 64. ジェネリックラムダ auto の意味 64 回答 ラムダ式自体がテンプレートな のではなく、ラムダ式の型(ク ロージャ型と言う)のoperator() (関数呼び出しオペレータ)がメ ンバ関数テンプレート
  65. 65. ジェネリックラムダ auto の意味 65 さっきの例 [](auto a, auto b) { return a + b; } ⇓ struct 絶対アクセスできないユニークな名前 { template<typename T, typename U> auto operator()(T a, U, b) const { return a + b; } };
  66. 66. ジェネリックラムダ auto の意味 66 ラムダキャプチャはコンストラクタの引数 [v = 42](auto a, auto b) { return a + b; } ⇓ struct 絶対直接アクセスできないユニークな名前 { 絶対直接アクセスできないコンストラクタ(int v) : v(v) {} template<typename T, typename U> auto operator()(T a, U, b) const { return a + b; } private: int v; };
  67. 67. ジェネリックラムダ auto の意味 67 余談 「ジェネリック」ってなんやねん、 テンプレートって呼べや… 「クロージャ」ってなんやねん、お 前クロージャじゃないやん… (注)個人の感想です
  68. 68. ジェネリックラムダ 68 関数ポインタへの 変換
  69. 69. ジェネリックラムダ 関数ポインタへの変換 69 ラムダキャプチャが空の場合、通常 のラムダ式と同じように関数ポイン タに変換可能 auto less = [](const auto& a, const auto& b) { return a < b; }; bool(*pf)(const int&, const double&) = less;
  70. 70. 通常関数の戻り値型推論 70
  71. 71. 通常関数の戻り値型推論 N2954 Unified Function Syntax http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2954.html N3386 Return type deduction for normal functions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3386.html N3582 Return type deduction for normal functions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3582.html N3638 Return type deduction for normal functions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3638.html 71
  72. 72. 通常関数の戻り値型推論 72 導入の背景
  73. 73. 通常関数の戻り値型推論 導入の背景 73 通常関数でも 戻り値型推論 がしたい!
  74. 74. 通常関数の戻り値型推論 74 書き方
  75. 75. 通常関数の戻り値型推論 書き方 75 戻り値型をautoにするだけ auto f() { return 42; // ← int に推論 } 変数宣言と同様autoをイロイロ修飾も可能 template <typename T> struct S { const auto& f() const { return v; } std::vector<T> v; };
  76. 76. 通常関数の戻り値型推論 書き方 76 使う前に推論が完了していれば、再帰でもOK auto f(int i) { if (i == 0) { return 1; // ← int に推論 } else { return i * f(i - 1); // ← 既に int に推論されているので OK } }
  77. 77. 通常関数の戻り値型推論 書き方 77 つまり、逆だとダメ auto f(int i) { if (i != 0) { return i * f(i - 1); // ← まだ推論されていないのでNG } else { return 1; // ← int に推論できるが、時既に🍣 } }
  78. 78. 通常関数の戻り値型推論 書き方 78 もちろん、条件演算子でもダメ auto f (int i) { return i == 0 ? 1 : i * f(i - 1); // ← まだ推論されていないのでNG }
  79. 79. 通常関数の戻り値型推論 書き方 79 先行宣言も可能だが、使う前に推論が完了してい ないとダメ auto f(); // ← 先行宣言 void g() { auto i = f(); // ← これはNG } auto f() { return 42; // ← int に推論 } void h() { auto i = f(); // ← これはOK }
  80. 80. 通常関数の戻り値型推論 書き方 80 先行宣言する場合、一部だけautoとかはダメ int f(); // ← 先行宣言 auto f() { return 42; // ← intに推論してくれても良さそうだけどダメ } auto g(); // ← 先行宣言 int g() { return 42; // ← 逆パターンもダメ }
  81. 81. 通常関数の戻り値型推論 書き方 81 関数テンプレートの特殊化とかでも混ざるのはダメ template<typename T> auto f(T v) { return v; } template<> int f<int>(int) { // ← ダメ return 42; }
  82. 82. 通常関数の戻り値型推論 書き方 82 仮想関数は戻り値型推論使えない struct S { virtual auto f() { return 42; // ← intに推論してくれても良さそうだけどダメ } }; オーバーライドのチェックとvtableのレイアウトが複雑になるからダメ、ら しい…
  83. 83. 通常関数の戻り値型推論 書き方 83 変数と違って、戻り値型にautoを使った場合、リスト初期化はできない auto v = { 1, 2, 3 }; // ← OK 変数のコピーリスト初期化の場合、 // std::initializer_listに推論される auto f() { return { 1, 2, 3 }; // ← NG 戻り値型推論の場合、リスト初期化はダメ } std::initializer_list が使用する配列が、関数ローカルになる(スタック上 にとられる)ため、戻り値を使用する時には既に破棄されていて UB に なってしまう、と言う理由らしい… (C++17 で RVO 必須になってもダメなものなんだろうか、ダメなんだろう な…)
  84. 84. 通常関数の戻り値型推論 84 SFINAE
  85. 85. 通常関数の戻り値型推論 SFINAE 85 戻り値型推論をさせている場合、SFINAEじゃなくてエラーらしい… (SFINAE分からない…) Since the return type is deduced by instantiating the template, if the instantiation is ill-formed, this causes an error rather than a substitution failure. This allows an auto function to return a lambda, which is not possible using the decltype(returned expression) pattern.
  86. 86. 通常関数の戻り値型推論 SFINAE 86 ちょっと勉強しました!(ほんのちょっとだけ…) auto で戻り値型推論させている 場合に、return 文に変な式出て きちゃったらSFINAEじゃなくてエ ラーだからね! SFINAE が効くのはあくまで関数宣言だけど、 戻り値型推論は関数定義本体見ないとダメだから、 SFINAE にならない、と言う事らしい…
  87. 87. 通常関数の戻り値型推論 SFINAE 87 SFINAE になる例 template<typename T> auto f(T p) -> decltype(p->m) { return p->m; } int f(...) { return 42; } int main() { return f(42); // auto f(T p) が SFINAE で候補から } // 外れて int f(...) が呼ばれる
  88. 88. 通常関数の戻り値型推論 SFINAE 88 SFINAE にならない例その1 template<typename T> auto f(T p) -> decltype(auto) { return p->m; } int f(...) { return 42; } int main() { return f(42); // auto f(T p) が候補から外れずに } // エラーになる
  89. 89. 通常関数の戻り値型推論 SFINAE 89 SFINAE にならない例その2 template<typename T> auto f(T p) { return p->m; } int f(...) { return 42; } int main() { return f(42); // auto f(T p) が候補から外れずに } // エラーになる
  90. 90. 関数の後置戻り値型のプ レースホルダ 通常関数の戻り値型推論のついで 90
  91. 91. 関数の後置戻り値型のプ レースホルダ 91 導入の背景
  92. 92. 関数の後置戻り値型のプ レースホルダ 導入の背景 92 通常関数の戻り値 型推論のついで
  93. 93. 関数の後置戻り値型のプ レースホルダ 導入の背景 93 ラムダ式の戻り値型 を型推論させたまま 参照修飾やconst修 飾させたい
  94. 94. 関数の後置戻り値型のプ レースホルダ 94 書き方
  95. 95. 関数の後置戻り値型のプ レースホルダ 書き方 95 そのまま []() -> const auto& { return variable; }
  96. 96. 関数の後置戻り値型のプ レースホルダ 書き方 96 余談 普通の関数の場合、謎の書き方もできる。 auto f() -> auto { // 全く要らねぇ return 42; } auto g() -> const auto& { // const auto& g() って書けよ return variable; }
  97. 97. decltype(auto) 通常関数の戻り値型推論のついで 97
  98. 98. decltype(auto) 98 導入の背景
  99. 99. decltype(auto) 導入の背景 99 通常関数の戻り値 型推論のついで
  100. 100. decltype(auto) 導入の背景 100 auto みたいに対象の式からう まいこと型推論してほしいけ ど、推論規則はdecltypeみた いに(参照は参照のまま)して ほしい
  101. 101. decltype(auto) 導入の背景 101 auto fwd(int& i) { return i; } この場合に int& になって欲しいけど、auto の型推論規則だ と int になっちゃう。 auto fwd(int& i) -> decltype(i) { return i; } だと int& になってくれるけど、二回書くのはちょっと…
  102. 102. decltype(auto) 102 書き方
  103. 103. decltype(auto) 書き方 103 そのまま decltype(auto) fwd(int& i) { return i; } 別に変数に使ってもOK int i = 42; int& ri = i; decltype(auto) j = ri;
  104. 104. decltype(auto) 書き方 104 式に括弧が付いてるか否かで型が変わ る場合があるので要注意 int i = 42; decltype(auto) j = i; // j は int decltype(auto) k = (i); // k は int&
  105. 105. decltype(auto) 書き方 105 おっさんは特に注意!!! decltype(auto) f() { int i = 42; return (i); // おっさんの書き方 }
  106. 106. 戻り値型推論の範囲拡大 CWG Issue 975. Restrictions on return type deduction for lambdas http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#975 106
  107. 107. 戻り値型推論の範囲拡大 107 対応の背景
  108. 108. 戻り値型推論の範囲拡大 対応の背景 108 戻り値型推論便利なんだけど、推 論してくれるのが return 文1つだけ の時って言う制限きつすぎね? 技術的にも何も難しくないし…
  109. 109. 戻り値型推論の範囲拡大 109 対応
  110. 110. 戻り値型推論の範囲拡大 対応 110 OK 通常関数の戻り値型推論のつ いでに範囲拡大しよう でも、return 文複数あったらそれ ぞれ独立で型推論した結果が全 部同じ型にならないとダメだよ。
  111. 111. 戻り値型推論の範囲拡大 対応 111 余談 言ってる意味は分かるし、修正 自体も良いと思うんだが、これを 規格のバグとしてC++11でも OKって言っちゃうのはどうなの よ…
  112. 112. ラムダ式の戻り値型推論 の変更 CWG Issue 1048. auto deduction and lambda return type deduction http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1048 112
  113. 113. ラムダ式の戻り値型推論の 変更 113 対応の背景
  114. 114. ラムダ式の戻り値型推論の 変更 対応の背景 114 auto の型推論規則と ラムダ式の戻り値型 推論規則が違うのキ モくね?
  115. 115. ラムダ式の戻り値型推論の 変更 115 対応
  116. 116. ラムダ式の戻り値型推論の 変更 対応 116 OK 通常関数の戻り値型推論の ついでに auto と一緒にしよう ただし、こいつは C++11 に対 するバグ修正扱いね
  117. 117. サイズ付きデアロケーショ ン関数 117
  118. 118. サイズ付きデアロケーション N3432 C++ Sized Deallocation http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3432.html N3536 C++ Sized Deallocation http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3536.html N3663 C++ Sized Deallocation http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3663.html N3778 C++ Sized Deallocation http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3778.html 118
  119. 119. サイズ付きデアロケーション 119 導入の背景
  120. 120. サイズ付きデアロケーション 導入の背景 120 1.デアロケーションの時にサイズ があった方が効率いんじゃね?(※) 2.クラス毎のデアロケーションには サイズ付きあるのに何でグローバ ルにはないの? ※ Kosaki - the malloc - 参照(©@kosaki55tea) https://www.youtube.com/watch?v=0-vWT-t0UHg https://www.slideshare.net/kosaki55tea/glibc-malloc
  121. 121. サイズ付きデアロケーション 121 シグネチャ
  122. 122. サイズ付きデアロケーション シグネチャ 122 通常オブジェクト用 void operator delete(void* ptr, std::size_t size) noexcept; void operator delete(void* ptr, std::size_t size, const std::nothrow_t&) noexcept; 配列用 void operator delete[](void* ptr, std::size_t size) noexcept; void operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) noexcept;
  123. 123. サイズ付きデアロケーション シグネチャ 123 ん?std::nothrow_t 付きの奴ら、呼ば れなくね?
  124. 124. サイズ付きデアロケーション シグネチャ 124 てへ、勢い余って追 加しちゃいました… C++17 では無くなってます。 LWG Issue 2458. N3778 and new library deallocation signatures http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2458
  125. 125. サイズ付きデアロケーション シグネチャ 125 素朴な疑問 サイズ付きと無し、 どちらが優先して呼 ばれるのか?
  126. 126. サイズ付きデアロケーション シグネチャ 126 回答 サイズ付き (そりゃそうか…)
  127. 127. サイズ付きデアロケーション シグネチャ 127 C++14 の規格にバ グがありました… CWG Issue 1788. Sized deallocation of array of non-class type http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1788
  128. 128. サイズ付きデアロケーション シグネチャ 128 サイズ付きとサイズ無しの両方が見つかった場合 に、サイズ付きが呼ばれるかどうかの規則は、 ちょっとメンドウ… 1. 対象の型が完全型で、かつ配列じゃ無ければ サイズ付き 2. 対象の型が完全型の配列で、かつ非自明なデ ストラクタがある場合はサイズ付き 3. 上記以外の場合は、規定無し(どっちが呼ばれ るか分からない)
  129. 129. サイズ付きデアロケーション シグネチャ 129 何でこんなメンドウ な規則になってる の?
  130. 130. サイズ付きデアロケーション シグネチャ 130 サイズ付き呼ぶためにはサイ ズ覚えとかなきゃならない。 でもサイズ覚えとくためには 余計な領域が必要になる。
  131. 131. サイズ付きデアロケーション シグネチャ 131 結論 サイズ付き呼び出 すの諦めよう! マジかよ…
  132. 132. サイズ付きデアロケーション シグネチャ 132 でも実は改めてサイズ 覚えなくてもいいケース がある… それがさっきの1と2の 条件です…
  133. 133. サイズ付きデアロケーション シグネチャ 133 1. 対象の型が完全型で、かつ配列じゃ無ければ サイズ付き 配列じゃないのでオブジェクトの型がわかればOK。 普通は変数の型(ポインタ型)からオブジェクトの型 が分かる。 万一ポインタが基底クラスの場合でも、当該基底ク ラスに仮想デストラクタが存在必要があるのでわざ わざそれ用にサイズ覚えとく必要が無い。 (ちなみに仮想デストラクタが存在しないとUB)
  134. 134. サイズ付きデアロケーション シグネチャ 134 2. 対象の型が完全型の配列で、かつ非自明なデ ストラクタがある場合はサイズ付き 配列だから対象の型のサイズ×配列の個数でサイ ズが求まる。 配列の場合、対象の型は変数の型と一致しなけれ ばならない(そうじゃないとUB)から覚えてなくても わかる。 非自明なデストラクタがある場合、delete時に全要 素にデストラクタ呼び出さなきゃならないから、もと もと配列の個数覚えてる。
  135. 135. サイズ付きデアロケーション シグネチャ 135 ちなみに、クラスにoperator deleteの定義が ある場合には両方見つかることはないので 注意。 クラスのoperator deleteはサイズ付きが優先 されるので、サイズ付きがある場合にはサイ ズ無しはそもそも探されない。 (ので、必ずサイズ付きが呼ばれる) つまり、サイズ付きがある場合には必ず余分な領域が取られてる…
  136. 136. サイズ付きデアロケーション シグネチャ 136 素朴な疑問 サイズ無しだけ ユーザ定義したら どうなる?
  137. 137. サイズ付きデアロケーション シグネチャ 137 回答 既定のサイズ付きは、互換性のためサ イズ無しを呼び出す。 ただし、この挙動は互換性のためであり、 将来は変更される可能性がある。 ユーザ定義する場合はサイズ付きと無 し両方提供せよ、とも書かれている。
  138. 138. サイズ付きデアロケーション シグネチャ 138 余談 Clang は 3.4 からサイズ付きデアロケーショ ンに対応しているが、3.7からはコンパイル時 に -fsized-deallocation フラグが必要になった。 これは、使用する標準ライブラリにサイズ付 きが無かった場合を考慮した結果。フラグ指 定無しでうまい事やるのが難しいらしい… https://reviews.llvm.org/D8467
  139. 139. constexpr 関数の制限緩和 N3597 Relaxing constraints on constexpr functions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3597.html N3652 Relaxing constraints on constexpr functions constexpr member functions and implicit const http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3652.html 139
  140. 140. constexpr 関数の制限緩和 140 対応の背景
  141. 141. constexpr 関数の制限緩和 対応の背景 141 constexpr 関数に実質 return文しか書けないの、 さすがに厳しすぎじゃね? (そお? by ボ村)
  142. 142. constexpr 関数の制限緩和 142 対応
  143. 143. constexpr 関数の制限緩和 対応 143 1. ローカル変数宣言が出来るようになった。ただし、 • staticやthread_localじゃないこと。 • 初期化されていること。 2. if文、switch文が使えるようになった。(gotoさんはダメ) 3. すべてのループ文が使えるようになった。 4. オブジェクトの修正が可能になった。ただし、当該オブ ジェクトの生存期間は、その定数式の評価中に始まって いること。 5. voidがリテラル型になったので、戻り値がvoidでも良く なった。
  144. 144. constexpr 関数の制限緩和 対応 144 他にもいっぱい変更点が あるけど、難しくて分から ないのでペーパー見て下 さい… でも、とりあえずだいぶ普通に関数が書けるようになりまし た…
  145. 145. constexpr メンバ関数の暗 黙のconst修飾廃止 N3598 constexpr member functions and implicit const http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3598.html N3652 Relaxing constraints on constexpr functions constexpr member functions and implicit const http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3652.html 145
  146. 146. constexpr メンバ関数の暗黙 のconst修飾廃止 146 導入の背景
  147. 147. constexpr メンバ関数の暗黙の const修飾廃止 導入の背景 147 中3女子がオコだから※ ※ C++11の糞仕様と戦ってアクセッサをconstexprにする http://boleros.hateblo.jp/entry/20130604/1370364968
  148. 148. constexpr メンバ関数の暗黙の const修飾廃止 導入の背景 148 constexprという予約語の字面のせいで時々誤解が起こるが、const性が 担保されるのは、評価が完了したコンパイル時定数のみである。 定数式評価中の文脈におけるオブジェクトのconst性とはまったく無縁で ある。 たとえコンパイル時であっても、非const rvalue/lvalue参照などの、あら ゆるvalue categoryの式が扱われる。 中略 constexprメンバ関数が暗黙でconst修飾されるのは論外である。 定数式の評価結果に対するconst性と、定数式評価中のconst性を取り 違えた、致命的な失策の、腐敗した糞仕様と言わざるをえない。 ボレロ村上:『C++11の糞仕様と戦ってアクセッサをconstexprにする』より
  149. 149. constexpr メンバ関数の暗黙 のconst修飾廃止 149 後方互換性
  150. 150. constexpr メンバ関数の暗黙の const修飾廃止 後方互換性 150 こんなコードはC++14で壊れる struct S { int f() { return 0; } constexpr int f() { return 42; } }; 下のf()はC++11ではconst修飾付きだが、C++14以 降ではconst修飾無しなので、上のf()と同じシグネ チャになってしまう。 C++11でもconst修飾はできるので、あらかじめつけ ておいた方が無難。(GCC、Clangは警告が出る)
  151. 151. 変数テンプレート N3615 Constexpr Variable Templates http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3615.pdf N3651 Variable Templates (Revision 1) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3651.pdf 151
  152. 152. 変数テンプレート 152 導入の背景
  153. 153. 変数テンプレート 導入の背景 153 型パラメータ化した 定数が欲しい こんなやつ template<typename T> constexpr T pi = T(3.1415926535897932385);
  154. 154. 変数テンプレート 導入の背景 154 現状の回避策 std::numeric_limitsがいい例 1. クラステンプレートの静的メンバ変数 std::numeric_limits<int>::is_signed 2. constexpr のテンプレート関数 std::numeric_limits<int>::max()
  155. 155. 変数テンプレート 155 書き方
  156. 156. 変数テンプレート 書き方 156 そのまんま template<typename T> constexpr T pi = T(3.1415926535897932385); 別に constexpr じゃなくてもいい template<typename T> T value = T(42);
  157. 157. 変数テンプレート 157 制限
  158. 158. 変数テンプレート 制限 158 変数テンプレートはテンプ レートテンプレートパラメー タには使えない。
  159. 159. deprecated属性 N3394 [[deprecated]] attribute http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3394.html N3760 [[deprecated]] attribute http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3760.html 159
  160. 160. deprecated属性 160 導入の背景
  161. 161. deprecated属性 導入の背景 161 何かみんなそれぞれ独自の 構文で非推奨属性つけられ るんだけど、せっかくC++11で 属性出来たんだし、これ標準 化した方がいんじゃね?
  162. 162. deprecated属性 162 書き方
  163. 163. deprecated属性 書き方 163 属性としてdeprecated を付ける [[deprecated]] auto f() { return 42; } 補足情報を付けることもできる [[deprecated("代わりにg使え")]] auto f() { return 42; }
  164. 164. deprecated属性 164 付加可能対象
  165. 165. deprecated属性 付加可能対象 165 クラス宣言 typedef名 変数 非スタティックデータメンバ 関数 列挙型 テンプレート特殊化
  166. 166. deprecated属性 166 注意 規格の非推奨機能に必ずついてい ると言う保証はない。 (規格書では、処理系で付けても良 い、的な扱いになっている)
  167. 167. メンバ初期化子と集成体 N3605 Member initializers and aggregates http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3605.html N3653 Member initializers and aggregates http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3653.html 167
  168. 168. メンバ初期化子と集成体 168 対応の背景
  169. 169. メンバ初期化子と集成体 対応の背景 169 メンバ初期化子がある だけの単なる構造体が 集成体初期化できない のは不便じゃね?
  170. 170. メンバ初期化子と集成体 対応の背景 170 例 struct S { int i; int j = 42; // ← メンバ初期化子 }; S s = { 1, 2 }; // ← NG メンバ初期化子があると集成体とは認められない ため、集成体初期化ができない
  171. 171. メンバ初期化子と集成体 171 対応
  172. 172. メンバ初期化子と集成体 対応 172 メンバ初期化子が あっても集成体と言 う事にしよう
  173. 173. メンバ初期化子と集成体 対応 173 そうするとこんなのもできるな。(規格書の例) struct S { int a; const char* b; int c; int d = b[a]; }; S ss = { 1, "asdf" }; // c = 0(int{}), d = 's'("asdf"[1]) なんでそんな事するかね…(個人の感想です)
  174. 174. 初期化リストの中括弧省 略可能範囲拡大 CWG Issue 1270. Brace elision in array temporary initialization http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1270 174
  175. 175. 初期化リストの中括弧省略 可能範囲拡大 175 対応の背景
  176. 176. 初期化リストの中括弧省略 可能範囲拡大 対応の背景 176 初期化リストによる初期化 std::vector<int> v1 = { 1, 2, 3 }; // ← OK std::array<int, 3> a1 = { 1, 2, 3 }; // ← OK std::vector<int> v2{ 1, 2, 3 }; // ← OK std::array<int, 3> a2{ 1, 2, 3 }; // ← NG なんでや!!!1!
  177. 177. 初期化リストの中括弧省略 可能範囲拡大 対応の背景 177 こんな例も… std::vector<int> f() { return { 1, 2, 3 }; // ← OK } std::array<int, 3> g() { return { 1, 2, 3 }; // ← NG } これはコピーリスト初期化なのに…
  178. 178. 初期化リストの中括弧省略 可能範囲拡大 178 対応
  179. 179. 初期化リストの中括弧省略 可能範囲拡大 対応 179 全部OKにしよう 当たり前すぎる…
  180. 180. リテラル演算子定義時の スペース省略 CWG Issue 1473. Syntax of literal-operator-id http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1473 180
  181. 181. リテラル演算子定義時のス ペース省略 181 対応の背景
  182. 182. リテラル演算子定義時のス ペース省略 対応の背景 182 これはOK void operator""△_s1(unsigned long long) { } これはNG void operator""_s2(unsigned long long) { } これってどうなの?
  183. 183. リテラル演算子定義時のス ペース省略 対応の背景 183 あと、これはOK?NG? void operator""△""△_s3() { } ※ 隣接する文字列リテラルはプリプロセス時に結合される
  184. 184. リテラル演算子定義時のス ペース省略 184 対応
  185. 185. リテラル演算子定義時のス ペース省略 対応 185 全部OKにしよう 当たり前すぎる…
  186. 186. std::nullptr_t 型の非型テン プレートパラメータ CWG Issue 1048. Non-type template parameters of type std::nullptr_t http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1398 186
  187. 187. std::nullptr_t 型の非型テン プレートパラメータ 187 対応の背景
  188. 188. std::nullptr_t 型の非型テンプ レートパラメータ 対応の背景 188 何か規格書の文言を忠実 に守るとstd::nullptr_t型の 非型テンプレートパラメー タに渡せる実引数が無い んだけど…
  189. 189. std::nullptr_t 型の非型テン プレートパラメータ 189 対応
  190. 190. std::nullptr_t 型の非型テンプ レートパラメータ 対応 190 非型テンプレートパラメー タがstd::nullptr_t型だった らnullptr渡せるようにしよ 当たり前すぎる… (実はどの処理系も忠実じゃなかった…)
  191. 191. 文脈依存変換の微調整 191
  192. 192. 文脈依存変換の微調整 N3253 A Proposal to Tweak Certain C++ Contextual Conversions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3253.pdf N3306 A Proposal to Tweak Certain C++ Contextual Conversions, v2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3306.pdf N3323 A Proposal to Tweak Certain C++ Contextual Conversions, v3 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3323.pdf 192
  193. 193. 文脈依存変換の微調整 193 対応の背景
  194. 194. 文脈依存変換の微調整 対応の背景 194 文脈依存変換が ちょっと微妙な気が するんだが…
  195. 195. 文脈依存変換の微調整 対応の背景 195 文脈依存変換が効くのは以下の4つ 1. 配列 new 式の最後の [] の中 2. delete 式の対象 3. 定数式 4. switch 文の () の中 これらの文脈で、式の型がクラス型の 場合に、ユーザ定義変換関数のみを使 用した暗黙変換が行われる。
  196. 196. 文脈依存変換の微調整 対応の背景 196 微妙な例(処理系による) template<typename T> struct S { S(T v) : v(v) {} operator T& () { return v; } operator T () const { return v; } T v; }; S<int*> p = new int(7); delete p; // エラー delete (p + 0); // オーケー delete +p; // オーケー
  197. 197. 文脈依存変換の微調整 197 対応
  198. 198. 文脈依存変換の微調整 対応 198 規格を明確化して、 ダメだったパターン もOKにしよう
  199. 199. 文脈依存変換の微調整 対応 199 変換規則 文脈で許される型(cv修飾や参照含む) へのexplicitでないユーザ定義変換を列 挙した時、その変換後の型は1種類で あること。 元のクラス型から対象の型への変換自 体は、通常のユーザ定義変換に従う。
  200. 200. メモリアロケーションの明 確化 200
  201. 201. メモリアロケーションの明確 化 N3433 Clarifying Memory Allocation http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3433.html N3537 Clarifying Memory Allocation http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3537.html N3664 Clarifying Memory Allocation http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3664.html 201
  202. 202. メモリアロケーションの明確 化 202 対応の背景
  203. 203. メモリアロケーションの明確 化 対応の背景 203 new式毎に必ずアロ ケーション関数呼ば なきゃならないのは 制約厳しすぎね?
  204. 204. メモリアロケーションの明確 化 204 対応
  205. 205. メモリアロケーションの明確 化 対応 205 OK new式毎にアロケー ション関数呼ばれる 「かも」に変更しよう
  206. 206. メモリアロケーションの明確 化 対応 206 実装は二つ以上のnew式に対するアロケーション関数呼び 出しをまとめても良い。 条件 1. あるnew式で割り当てられるオブジェクトが他のnew式で 割り当てられるオブジェクトの生存期間を包含する。 2. それらが同じグローバルアロケーション関数で割り当て られる。 3. アロケーション関数が例外を投げる場合、どちらの式の 例外も最初にキャッチするハンドラが一緒である。
  207. 207. メモリアロケーションの明確 化 対応 207 アロケーション関数呼び出しをまとめる場合、 まとめられた呼び出しの際のサイズパラメー タは、まとめられなかった場合の各呼び出し サイズの合計に、各オブジェクトのアラインに 必要なパディングサイズを加えたものを超え てはならない。
  208. 208. メモリアロケーションの明確 化 対応 208 あ、アロケーション関数、デアロケーション関 数、malloc 系関数は、 (ユーザ定義版も含 めて)データレース起こしちゃダメってのも、 より明確に記載されました。

×