ついに5回目。
今回はラムダ式に関してやります。
ラムダ式自体はC++に限らずほかの言語でも取り入れているところは多くてRubyだと
1 2 3 |
l = ->(x){p x} a = 3 l.call(a) => 3 |
こんな感じで書けますがC++では
1 2 3 |
int a = 3; auto l = [a] { std::cout << a << std::endl; }; // 変数aをコピーキャプチャする l(); |
こんな感じです。
C++でのラムダ式は11から使用できるようになったのですがC++17でラムダに関する変更がありましたそれを今回やります。
・ラムダ式での*thisのコピーキャプチャ
ラムダ式では例のように値をキャプチャすることができます。
例では変数をしていしてラムダ内で使用できるようになっていますがこの例だと値渡しになっています。
参照渡しにするには
[&a]
とかにすると参照渡しとなりラムダ式内で変更するとその値が外で宣言した変数も変わります。
[&]とするとすべての外部変数が参照で、[=]だと値渡しとなります。
でここにthisを使用するとthisポインタがコピーされます。
が、このthisポインタが指すオブジェクトがすでに破棄されている可能性があります。
例えば非同期処理で動作していた場合thisポインタが破棄されている可能性があるのでラムダ式内で使用すると..
これがC++14まででした。
今回C++17では[this]とすることでキャプチャ時点でのthisオブジェクトをコピーできるようになりました。
これはかなり便利なのではないでしょうか。
ちなみに[=, *this]とするとデフォルトのコピーキャプチャと併用することができるようです。
[this, *this]はダメとのこと。
がここで注意。
[this]でキャプチャするとオブジェクトはデフォルトでconstになるとのこと。[this]の場合はポインタであるため書き換えができ、非constでメンバ関数が
呼び出せます。
[this]の場合で非constメンバ関数を呼び出す場合はmutableとつける必要がある。
・constexpr ラムダ
constexpr自体はC++11で追加されたものです。
constexprは、汎用的に定数式を表現するための機能です。
なのでC++11より前は
1 2 3 4 5 |
struct X { int n; }; int main() { const X x = {10}; int a[x.n] = {1}; } |
こんな感じだとエラーになりますがconstの部分をC++11ではconstexprにすると
1 2 3 4 5 |
struct X { int n; }; int main() { constexpr X x = {10}; int a[x.n] = {1}; } |
OKになります。(このままだと変数未使用で警告が出たりしますが)
C++17ではラムダ式をconstexpr関数に使用することができるため
1 2 |
auto add = [](int x) constexpr { return x + 1; }; static_assert(add(1) == 2); |
こんな感じで書くことができます。
暗黙的にconstexprその結果の要件を満たしている場合、constexpr関数となります。
1 2 3 4 5 6 |
auto answer = [](int n) { return n + 1; }; constexpr int response = answer(1); |
この機能が必要になった背景を引用すると、
ラムダがconstexprでないことによって不要に複雑なコードを書くことは混乱のもとであるとして、C++17にconstexprラムダが提案された。
早い対応。
短いけど今回はこれまで。