Skip to content

Latest commit

 

History

History
52 lines (40 loc) · 2.87 KB

File metadata and controls

52 lines (40 loc) · 2.87 KB

暗黙のラムダキャプチャを簡略化

  • cpp20[meta cpp]

概要

ここでは、ラムダ式での暗黙のキャプチャについて、以下のN個の問題を解決する:

  1. ラムダ式内でのdecltype((x))の使用
  2. ラムダ式での構造化束縛のキャプチャ

ラムダ式でコピーキャプチャした変数を、評価されない文脈のみで使用した場合に、その変数はクロージャオブジェクトのメンバ変数になることを仮定していた。この変更ではその仮定をやめ、式の型のみを規定するようになった。

void f() {
  float x, &r = x;
  [=] {
    decltype(x) y1;        // y1はfloat型をもつ
    decltype((x)) y2 = y1; // y2はconst float&型をもつ。ラムダ式がmutableではなくxが左辺値であるため
    decltype(r) r1 = y1;   // r1はfloat&型をもつ
    decltype((r)) r2 = y2; // r2はconst float&型をもつ
  };
}

本提案では一旦、構造化束縛で導入された名前はラムダ式でキャプチャできない、と明記された。その後、「構造化束縛を拡張して通常の変数宣言のように使用できるようにする」の仕様でそれが可能となったため、この部分は打ち消された。

仕様

odr-usable(=ある名前の定義がその場所で見つかるか)という用語を導入して、lamda式でキャプチャできるものの増加に対して、規格文面の整理が行われた。

ローカル変数のように、ローカルでodr-usedされる時に、その場所ではodr-usableでないとき、そのプログラムは適格ではない。

void f(int n) {
  [] { n = 1; };                // error: nが使われようとしているのはlambda式の中なので、odr-usableではない
  struct A {
    void f() { n = 2; }         // error: nが使われようとしているのは関数定義スコープの中なので、odr-usableではない
  };
  void g(int = n);              // error: nが使われようとしているのはlambda式以外の関数引数スコープの中なので、odr-usableではない
  [=](int k = n) {};            // error: n is not odr-usable due to being
                                // outside the block scope of the lambda-expression
  [&] { [n]{ return n; }; };    // OK
}

関連項目

参照