構造化束縛は便利そうに見えますが、制約はもちろんあります。
複雑なクラス型に対して使えないか調べてみましたが、サポートしているのは本当にシンプルなクラス型だけのようです。
例えば以下の3つのケースでは構造化束縛は機能しません。
以下のソースコードは動作しないことをチェックしています。(コンパイルは通りません)
マクロについては クロスコンパイルのための組み込みマクロ を参照くださいね。
main.cpp.
1 #if __cplusplus < 201703L 2 # pragma message "-std=c++17を指定してください" 3 #endif 4 5 struct Foo { 6 int a; 7 struct { 8 int b; 9 }; 10 }; 11 12 struct PS { 13 PS(int a,int b) : M_a_{a}, M_b_{b} {} 14 int M_a_; 15 private: 16 int M_b_; 17 }; 18 19 struct base { int x; }; 20 21 struct derived : public base 22 { int y; }; 23 24 int main() 25 { 26 Foo f{1,2}; 27 PS p{1,2}; 28 derived d{1,2}; 29 >> 30 auto [a] = f; >> 31 auto [c,d] = p; >> 32 auto [e] = d; 33 34 return 0; 35 }
これを gcc でコンパイルしようとすると怒られます。
$ g++ main.cpp -std=c++17 main.cpp: In function ‘int main()’: main.cpp:30:7: error: cannot decompose class type ‘Foo’ because it has an anonymous struct member auto [a] = f; ^~~ main.cpp:7:2: note: declared here struct { ^~~~~~ main.cpp:31:11: error: conflicting declaration ‘auto d’ auto [c,d] = p; ^ main.cpp:28:10: note: previous declaration as ‘derived d’ derived d{1,2}; ^ main.cpp:32:7: error: cannot decompose class type ‘derived’: both it and its base class ‘base’ have non-static data members auto [e] = d; ^~~
まずは無名クラスですね。
1 struct Foo { 2 int a; 3 struct { 4 int b; 5 }; 6 }; 22 Foo f{1,2}; >> 26 auto [a] = f;
このように展開する再、 Foo クラス内に無名クラスが入っているとコンパイラに怒られます。
次のプライベートメンバーの展開は特に気をつけたいです。
12 struct PS { 13 PS(int a,int b) : M_a_{a}, M_b_{b} {} 14 int M_a_; 15 private: 16 int M_b_; 17 }; 27 PS p{1,2}; >> 31 auto [c,d] = p;
メンバー変数が隠蔽されてるだけでコンパイルエラーになるので、これは結構厳しい制約ですよね。
最後は継承をしているオブジェクトの展開です。
19 struct base { int x; }; 20 21 struct derived : public base 22 { int y; }; 28 derived d{1,2}; >> 32 auto [e] = d;
継承を良く使う人にとっては悪いニュースかもしれないです…
(´・ω・`)
Copyright 2017-2018, by Masaki Komatsu