構造化束縛は便利そうに見えますが、制約はもちろんあります。
複雑なクラス型に対して使えないか調べてみましたが、サポートしているのは本当にシンプルなクラス型だけのようです。
例えば以下の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