C++20 で指示付き初期化子を使ったキーワード引数
C++20 で指示付き初期化子が実装されました。
指示付き初期化子はクラスを初期化する時に『任意のメンバ変数』を指定して初期化する事ができます。
struct pos{ int x; int y; int z; }; // .メンバ変数名 = で初期化できる pos p{ .x = 1, .y = 2, .z = 3 };
これを利用してキーワード引数っぽい関数を定義してみました。
#include <iostream> const auto disp = [] { // 引数を受け取るクラスを定義しておく // クラス定義を公開したくないので致し方なくクロージャ化 struct pos_t { int x; int y; int z = 0; }; return [](pos_t pos) { std::cout << "x = " << pos.x << std::endl; std::cout << "y = " << pos.y << std::endl; std::cout << "z = " << pos.z << std::endl; }; }(); int main(){ // 指示付き初期化子を利用してキーワード引数っぽく渡す disp({ .x = 1, .y = 2 }); std::cout << "---" << std::endl; disp({ .x = 1, .z = 3 }); return 0; } /* output: x = 1 y = 2 z = 0 --- x = 1 y = 0 z = 3 */
引数として受け取るクラスを定義しておいて、そのクラスに対して指示付き初期化子で値を渡すようにしています。
本当は
auto disp(struct { int x; int y; int z = 0; } pos) { // ... }
みたいに引数で直接匿名クラスが定義できればいいんですが、こういう書き方はできないので仕方なくラムダのスコープ内でクラスを定義するようにしています。
あと指示付き初期化子の制限で『指示子の順序が宣言の順序と一致しない』とエラーになるので次のようにもかけません。
// Error: 指示子の順序が宣言の順序と一致しない disp({ .y = 2, .x = 1 });
うーんキーワード引数で順序によってエラーになってしまうのはちょっと微妙ですねえ。
C++ で気持ちよくキーワード引数をかける日は来るのだろうか…。