Repository navigation
Expand file tree
/
Copy pathreflection.html
More file actions
1092 lines (967 loc) · 154 KB
/
Copy pathreflection.html
File metadata and controls
1092 lines (967 loc) · 154 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html class="cpprefjp" lang="ja" itemscope="" itemtype="http://schema.org/WebPage">
<head>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NXNBNVBTJS"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-NXNBNVBTJS');
</script>
<meta charset="UTF-8">
<title>静的リフレクション [P2996R13] - cpprefjp C++日本語リファレンス</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="keywords" content="
C++,標準ライブラリ,リファレンス,ドキュメント,STL,std,cpp26
">
<meta name="title" content="静的リフレクション [P2996R13] - cpprefjp C++日本語リファレンス" />
<meta itemprop="name" content="静的リフレクション [P2996R13] - cpprefjp C++日本語リファレンス" />
<meta property="og:title" content="静的リフレクション [P2996R13] - cpprefjp C++日本語リファレンス" />
<meta property="og:url" content="https://cpprefjp.github.io/lang/cpp26/reflection.html" />
<meta property="og:site_name" content="cpprefjp - C++日本語リファレンス" />
<meta property="og:type" content="article" />
<meta property="og:description" content="C++26では、コンパイル時にプログラムの構造を検査・操作できる「静的リフレクション (static reflection)」機能を導入する。" />
<meta property="og:image" content="" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="静的リフレクション [P2996R13] - cpprefjp C++日本語リファレンス" />
<meta name="twitter:url" content="https://cpprefjp.github.io/lang/cpp26/reflection.html" />
<meta name="twitter:description" content="C++26では、コンパイル時にプログラムの構造を検査・操作できる「静的リフレクション (static reflection)」機能を導入する。" />
<meta name="twitter:image" content="" />
<link rel="alternate" type="application/atom+xml" title="Atom" href="https://cpprefjp.github.io/rss.xml" />
<link rel="apple-touch-icon" sizes="180x180" href="../../static/favicons/apple-touch-icon.png?cachebust=807374ab51c48a5ce84749cf2ad281ba69eb3e58">
<link rel="icon" type="image/png" sizes="32x32" href="../../static/favicons/favicon-32x32.png?cachebust=807374ab51c48a5ce84749cf2ad281ba69eb3e58">
<link rel="icon" type="image/png" sizes="16x16" href="../../static/favicons/favicon-16x16.png?cachebust=807374ab51c48a5ce84749cf2ad281ba69eb3e58">
<link rel="manifest" href="../../manifest.json?cachebust=807374ab51c48a5ce84749cf2ad281ba69eb3e58">
<meta name="theme-color" content="#f5f8fc">
<link rel="stylesheet" href="../../static/pygments/default.css?cachebust=807374ab51c48a5ce84749cf2ad281ba69eb3e58">
<!-- <link rel="stylesheet" href="../../static/css/root.css"> -->
<link href="../../static/kunai/css/kunai-stage-0.css?cachebust=807374ab51c48a5ce84749cf2ad281ba69eb3e58" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-1.css?cachebust=807374ab51c48a5ce84749cf2ad281ba69eb3e58" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-2.css?cachebust=807374ab51c48a5ce84749cf2ad281ba69eb3e58" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-3.css?cachebust=807374ab51c48a5ce84749cf2ad281ba69eb3e58" rel="stylesheet">
<script type="text/javascript" src="../../static/kunai/js/kunai-vendor.js?cachebust=807374ab51c48a5ce84749cf2ad281ba69eb3e58"></script>
<script type="text/javascript" src="../../static/kunai/js/kunai.js?cachebust=807374ab51c48a5ce84749cf2ad281ba69eb3e58"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
var kn = new Kunai;
kn.cpprefjp();
});
</script>
</head>
<body>
<header data-kunai-mdinfo="{"meta": {"cpp": ["cpp26"]}, "sources": [{"id": "dc713454112d0f6457b061ff4f904f2d28f4f1a3", "source": "#include <meta>\n#include <print>\n#include <string>\n\nstruct Point {\n int x;\n int y;\n std::string name;\n};\n\nint main() {\n Point p{10, 20, \"origin\"};\n\n template for (constexpr auto m :\n std::define_static_array(std::meta::nonstatic_data_members_of(^^Point,\n std::meta::access_context::unchecked()))) {\n std::println(\"{}: {}\", std::meta::identifier_of(m), p.[:m:]);\n }\n}\n"}, {"id": "1d0e5e701108bc287a38e926f0274b36ce3c7637", "source": "#include <meta>\n#include <print>\n#include <string_view>\n#include <type_traits>\n\nenum class Color { red, green, blue };\n\ntemplate <typename E>\n requires std::is_enum_v<E>\nconstexpr std::string_view to_string(E value) {\n template for (constexpr auto e : std::define_static_array(std::meta::enumerators_of(^^E))) {\n if (value == [:e:]) {\n return std::meta::identifier_of(e);\n }\n }\n return \"<unknown>\";\n}\n\nint main() {\n std::println(\"{}\", to_string(Color::red));\n std::println(\"{}\", to_string(Color::green));\n std::println(\"{}\", to_string(Color::blue));\n}\n"}, {"id": "debfb987ba31357c31e59a06c81bbfcef765290d", "source": "#include <meta>\n#include <print>\n\nvoid process(int id, double value, const char* name) {}\n\nint main() {\n template for (constexpr auto p : std::define_static_array(std::meta::parameters_of(^^process))) {\n std::println(\"\u30d1\u30e9\u30e1\u30fc\u30bf: {} (\u578b: {})\",\n std::meta::identifier_of(p),\n std::meta::display_string_of(std::meta::type_of(p)));\n }\n}\n"}, {"id": "cc4705aa3432d48637c425007ea1cf6cb1965a67", "source": "#include <meta>\n#include <functional>\n#include <string>\n#include <print>\n#include <concepts>\n#include <cstddef>\n\n// std::hash<T>\u304c\u4f7f\u7528\u53ef\u80fd\u304b\u3092\u5224\u5b9a\u3059\u308b\u30b3\u30f3\u30bb\u30d7\u30c8\ntemplate <class T>\nconcept has_std_hash = requires(const T& x) {\n { std::hash<T>{}(x) } -> std::convertible_to<std::size_t>;\n};\n\ntemplate <class T>\nconstexpr std::size_t hash_value(const T& obj) {\n if constexpr (has_std_hash<T>) {\n // std::hash\u304c\u7279\u6b8a\u5316\u3055\u308c\u3066\u3044\u308c\u3070\u5229\u7528\u3059\u308b\n return std::hash<T>{}(obj);\n } else {\n // \u7279\u6b8a\u5316\u3055\u308c\u3066\u3044\u306a\u3051\u308c\u3070\u3001\u5404\u30e1\u30f3\u30d0\u306e\u30cf\u30c3\u30b7\u30e5\u5024\u3092\u518d\u5e30\u7684\u306b\u8a08\u7b97\u3057\u3066XOR\u3067\u5408\u6210\n std::size_t result = 0;\n template for (constexpr auto m :\n std::define_static_array(std::meta::nonstatic_data_members_of(^^T,\n std::meta::access_context::unchecked()))) {\n result ^= hash_value(obj.[:m:]);\n }\n return result;\n }\n}\n\nstruct Inner {\n int a;\n std::string b;\n};\n\nstruct Outer {\n int x;\n Inner inner; // \u30cd\u30b9\u30c8\u3057\u305f\u30af\u30e9\u30b9\u578b\u3082\u518d\u5e30\u7684\u306b\u30cf\u30c3\u30b7\u30e5\u5316\u3055\u308c\u308b\n};\n\nint main() {\n Outer o1{10, {1, \"hello\"}};\n Outer o2{10, {1, \"hello\"}};\n Outer o3{10, {2, \"hello\"}};\n\n std::println(\"hash(o1) == hash(o2): {}\", hash_value(o1) == hash_value(o2));\n std::println(\"hash(o1) == hash(o3): {}\", hash_value(o1) == hash_value(o3));\n}\n"}, {"id": "bdb11c56867858a5ff6a07550d64fcac41d41802", "source": "#include <meta>\n#include <cstdio>\n#include <format>\n#include <print>\n#include <stdexcept>\n#include <string_view>\n\n// \u5024\u306e\u7bc4\u56f2\u3092\u8868\u3059\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u30af\u30e9\u30b9\nstruct IntRange {\n int min_value;\n int max_value;\n};\n\nstruct FloatRange {\n double min_value;\n double max_value;\n};\n\nstruct Config {\n [[=IntRange{1, 65535}]] int port;\n [[=IntRange{1, 300}]] int timeout_seconds;\n [[=FloatRange{0.0, 1.0}]] double sampling_rate;\n int retry_count; // \u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u304c\u306a\u3044\u30e1\u30f3\u30d0\u5909\u6570\u306f\u691c\u8a3c\u3057\u306a\u3044\n};\n\n// IntRange\u3068FloatRange\u306e\u3069\u3061\u3089\u306b\u3082\u4f7f\u3048\u308b\u691c\u8a3c\u51e6\u7406\ntemplate <class R, class T>\nvoid check_range(std::string_view name, T value, R range) {\n if (value < range.min_value || range.max_value < value) {\n throw std::out_of_range{\n std::format(\"{}: {}\u306f{}\u4ee5\u4e0a{}\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044\",\n name,\n value,\n range.min_value,\n range.max_value)};\n }\n}\n\n// \u7bc4\u56f2\u306e\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u304c\u4ed8\u52a0\u3055\u308c\u305f\u30e1\u30f3\u30d0\u5909\u6570\u306e\u5024\u3092\u691c\u8a3c\u3059\u308b\ntemplate <class T>\nvoid validate(const T& obj) {\n template for (constexpr auto m :\n std::define_static_array(std::meta::nonstatic_data_members_of(^^T,\n std::meta::access_context::unchecked()))) {\n static constexpr auto int_annotations = std::define_static_array(\n std::meta::annotations_of_with_type(m, ^^IntRange));\n static constexpr auto float_annotations = std::define_static_array(\n std::meta::annotations_of_with_type(m, ^^FloatRange));\n\n // \u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u306f\u5024\u306e\u30ea\u30d5\u30ec\u30af\u30b7\u30e7\u30f3\u3067\u306f\u306a\u3044\u305f\u3081\u3001\n // constant_of()\u3067\u5024\u3092\u53d6\u308a\u51fa\u3057\u3066\u304b\u3089\u30b9\u30d7\u30e9\u30a4\u30b9\u3059\u308b\n if constexpr (int_annotations.size() > 0) {\n check_range(std::meta::identifier_of(m), obj.[:m:],\n [:std::meta::constant_of(int_annotations[0]):]);\n }\n else if constexpr (float_annotations.size() > 0) {\n check_range(std::meta::identifier_of(m), obj.[:m:],\n [:std::meta::constant_of(float_annotations[0]):]);\n }\n }\n}\n\nint main() {\n // \u3059\u3079\u3066\u7bc4\u56f2\u5185\u306a\u306e\u3067\u3001\u4f8b\u5916\u306f\u9001\u51fa\u3055\u308c\u306a\u3044\n validate(Config{\n .port = 8080,\n .timeout_seconds = 30,\n .sampling_rate = 0.5,\n .retry_count = 3\n });\n\n try {\n // port\u304c\u7bc4\u56f2\u5916\n validate(Config{\n .port = 0,\n .timeout_seconds = 30,\n .sampling_rate = 0.5,\n .retry_count = 3\n });\n } catch (const std::out_of_range& e) {\n std::println(stderr, \"{}\", e.what());\n }\n\n try {\n // sampling_rate\u304c\u7bc4\u56f2\u5916\n validate(Config{\n .port = 8080,\n .timeout_seconds = 30,\n .sampling_rate = 1.5,\n .retry_count = 3\n });\n } catch (const std::out_of_range& e) {\n std::println(stderr, \"{}\", e.what());\n }\n}\n"}, {"id": "dda32638040f23bdbb6ad2454f0e3c735535df95", "source": "#include <meta>\n#include <format>\n#include <print>\n#include <stdexcept>\n#include <string>\n#include <string_view>\n\n// \u30aa\u30d7\u30b7\u30e7\u30f3\u306e\u77ed\u7e2e\u540d\u3092\u8868\u3059\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\nstruct Short {\n char name;\n};\n\n// \u30aa\u30d7\u30b7\u30e7\u30f3\u306e\u8aac\u660e\u3092\u8868\u3059\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\nstruct Help {\n const char* text;\n};\n\nstruct Args {\n [[=Short{'n'}, =Help{std::define_static_string(\"\u6328\u62f6\u3059\u308b\u76f8\u624b\u306e\u540d\u524d\")}]]\n std::string name;\n\n [[=Short{'c'}, =Help{std::define_static_string(\"\u6328\u62f6\u3092\u7e70\u308a\u8fd4\u3059\u56de\u6570\")}]]\n int count = 1;\n};\n\nvoid assign(std::string& member, std::string_view value) {\n member = value;\n}\n\nvoid assign(int& member, std::string_view value) {\n member = std::stoi(std::string{value});\n}\n\n// \u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u304b\u3089\u30d8\u30eb\u30d7\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u751f\u6210\u3059\u308b\ntemplate <class T>\nvoid print_help() {\n std::println(\"\u30aa\u30d7\u30b7\u30e7\u30f3:\");\n template for (constexpr auto m :\n std::define_static_array(std::meta::nonstatic_data_members_of(^^T,\n std::meta::access_context::unchecked()))) {\n static constexpr auto shorts = std::define_static_array(\n std::meta::annotations_of_with_type(m, ^^Short));\n static constexpr auto helps = std::define_static_array(\n std::meta::annotations_of_with_type(m, ^^Help));\n\n std::println(\" -{}, --{:<8} {}\",\n [:std::meta::constant_of(shorts[0]):].name,\n std::meta::identifier_of(m),\n [:std::meta::constant_of(helps[0]):].text);\n }\n}\n\n// \u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u3092\u3082\u3068\u306b\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5f15\u6570\u3092\u89e3\u6790\u3059\u308b\ntemplate <class T>\nT parse(int argc, const char* const* argv) {\n T args{};\n for (int i = 1; i < argc; ++i) {\n std::string_view arg = argv[i];\n bool matched = false;\n\n template for (constexpr auto m :\n std::define_static_array(std::meta::nonstatic_data_members_of(^^T,\n std::meta::access_context::unchecked()))) {\n static constexpr auto shorts = std::define_static_array(\n std::meta::annotations_of_with_type(m, ^^Short));\n constexpr std::string_view long_name = std::meta::identifier_of(m);\n constexpr char short_name = [:std::meta::constant_of(shorts[0]):].name;\n\n bool is_long = arg.starts_with(\"--\") && arg.substr(2) == long_name;\n bool is_short = arg.size() == 2 && arg[0] == '-' && arg[1] == short_name;\n\n if (is_long || is_short) {\n if (++i == argc) {\n throw std::invalid_argument{std::format(\"{}: \u5024\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u306a\u3044\", arg)};\n }\n assign(args.[:m:], argv[i]);\n matched = true;\n break;\n }\n }\n\n if (!matched) {\n throw std::invalid_argument{std::format(\"{}: \u4e0d\u660e\u306a\u30aa\u30d7\u30b7\u30e7\u30f3\", arg)};\n }\n }\n return args;\n}\n\nint main() {\n print_help<Args>();\n\n // \u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5f15\u6570\u3092\u6a21\u3057\u305f\u30c7\u30fc\u30bf\n const char* argv[] = {\"greet\", \"--name\", \"wg21\", \"-c\", \"3\"};\n Args args = parse<Args>(5, argv);\n\n for (int i = 0; i < args.count; ++i) {\n std::println(\"Hello {}\", args.name);\n }\n}\n"}, {"id": "4545275173341dc590e588f8caa32b37dd2755d4", "source": "#include <meta>\n#include <concepts>\n#include <format>\n#include <print>\n#include <string>\n#include <string_view>\n\n// JSON\u306e\u30ad\u30fc\u540d\u3092\u5909\u66f4\u3059\u308b\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\nstruct Rename {\n const char* name;\n};\n\n// \u30b7\u30ea\u30a2\u30e9\u30a4\u30ba\u306e\u5bfe\u8c61\u304b\u3089\u5916\u3059\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\nstruct Skip {};\n\nstruct Address {\n std::string city;\n int postal_code;\n};\n\nstruct Person {\n [[=Rename{std::define_static_string(\"first name\")}]] std::string first;\n [[=Rename{std::define_static_string(\"last name\")}]] std::string last;\n int age;\n Address address; // \u30cd\u30b9\u30c8\u3057\u305f\u30af\u30e9\u30b9\u3082\u518d\u5e30\u7684\u306b\u5909\u63db\u3055\u308c\u308b\n [[=Skip{}]] std::string password; // \u30b7\u30ea\u30a2\u30e9\u30a4\u30ba\u3057\u306a\u3044\n};\n\ntemplate <class T>\nstd::string to_json(const T& value) {\n if constexpr (std::integral<T> || std::floating_point<T>) {\n return std::format(\"{}\", value);\n }\n else if constexpr (std::convertible_to<T, std::string_view>) {\n return std::format(\"\\\"{}\\\"\", value);\n }\n else {\n std::string result = \"{\";\n bool is_first = true;\n\n template for (constexpr auto m :\n std::define_static_array(std::meta::nonstatic_data_members_of(^^T,\n std::meta::access_context::unchecked()))) {\n static constexpr auto skips = std::define_static_array(\n std::meta::annotations_of_with_type(m, ^^Skip));\n\n if constexpr (skips.size() == 0) {\n static constexpr auto renames = std::define_static_array(\n std::meta::annotations_of_with_type(m, ^^Rename));\n\n // Rename\u30a2\u30ce\u30c6\u30fc\u30b7\u30e7\u30f3\u304c\u3042\u308c\u3070\u305d\u306e\u540d\u524d\u3092\u3001\u306a\u3051\u308c\u3070\u30e1\u30f3\u30d0\u5909\u6570\u540d\u3092\u30ad\u30fc\u306b\u3059\u308b\n constexpr std::string_view key = [] {\n if constexpr (renames.size() > 0) {\n return std::string_view{[:std::meta::constant_of(renames[0]):].name};\n }\n else {\n return std::meta::identifier_of(m);\n }\n }();\n\n if (!is_first) {\n result += ',';\n }\n is_first = false;\n result += std::format(\"\\\"{}\\\":{}\", key, to_json(value.[:m:]));\n }\n }\n return result + '}';\n }\n}\n\nint main() {\n Person person{\n .first = \"Taro\",\n .last = \"Yamada\",\n .age = 30,\n .address = {.city = \"Tokyo\", .postal_code = 1000001},\n .password = \"secret\"\n };\n\n std::println(\"{}\", to_json(person));\n}\n"}], "page_id": ["lang", "cpp26", "reflection"]}">
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../index.html">
<div class="title-wrapper clearfix">
<div class="title">cpprefjp - C++日本語リファレンス</div>
</div>
</a>
</div>
<div class="collapse navbar-collapse" id="navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li>
<div class="google-search">
<script>
(function() {
var cx = '013316413321391058734:ji_u66hl7hq';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
'//www.google.com/cse/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
</script>
<div class="gcse-search"></div>
</div>
</li>
<li>
<a href="https://github.com/cpprefjp/site">GitHub Project</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<main id="main" role="main">
<div class="container-fluid">
<div class="row">
<div class="col-sm-9 col-sm-push-3" itemscope itemtype="http://schema.org/Article">
<div class="row">
<div class="col-sm-12 google-search-result">
<gcse:searchresults></gcse:searchresults>
</div>
</div>
<div class="row">
<div class="col-sm-12 content-header">
<ol class="breadcrumb">
<li itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<a href="../../index.html" itemprop="url">
<i class="fa fa-fw fa-home"></i>
</a>
</span>
</li>
<li itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<a href="../../lang.html" itemprop="url">
<span itemprop="name">言語機能</span>
</a>
</span>
</li>
<li itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<a href="../../lang/cpp26.html" itemprop="url">
<span itemprop="name">C++26</span>
</a>
</span>
</li>
<li class="active" itemscope itemtype="http://www.schema.org/SiteNavigationElement">
<span>
<span itemprop="name">静的リフレクション [P2996R13]</span>
</span>
</li>
</ol>
<div class="crsearch"></div>
</div>
</div>
<div class="row">
<div class="col-sm-12 edit-button">
<p class="text-right"><small>
最終更新日時:
<time itemprop="datePublished" class="js-local-time"
datetime="2026-10-03T22:31:04+09:00">
2026年10月03日 22時31分04秒 (JST)
</time>
<br/>
<span itemprop="author" itemscope itemtype="http://schema.org/Person">
<span itemprop="name">Akira Takahashi</span>
</span>
が更新
</small></p>
<script>
(function () {
// 最終更新日時を閲覧者のローカルタイムゾーンで表示し直す (issue #53 の正規化)。
// JS が無効な環境ではサーバ生成の JST 表記がそのまま残る。
function pad(n) { return (n < 10 ? '0' : '') + n; }
var els = document.querySelectorAll('time.js-local-time[datetime]');
for (var i = 0; i < els.length; i++) {
var el = els[i];
var d = new Date(el.getAttribute('datetime'));
if (isNaN(d.getTime())) { continue; }
var tz = '';
try {
var parts = new Intl.DateTimeFormat(undefined, { timeZoneName: 'short' }).formatToParts(d);
for (var j = 0; j < parts.length; j++) {
if (parts[j].type === 'timeZoneName') { tz = parts[j].value; break; }
}
} catch (e) {}
el.textContent = d.getFullYear() + '年' + pad(d.getMonth() + 1) + '月' + pad(d.getDate()) + '日 '
+ pad(d.getHours()) + '時' + pad(d.getMinutes()) + '分' + pad(d.getSeconds()) + '秒'
+ (tz ? ' (' + tz + ')' : '');
}
})();
</script>
<p class="text-right">
<a class="history" target="_blank" href="https://github.com/cpprefjp/site/commits/master/lang/cpp26/reflection.md">
<span class="fa fa-fw fa-clock-o fa-flip-horizontal"></span>履歴
</a>
<a class="edit" target="_blank" href="https://github.com/cpprefjp/site/edit/master/lang/cpp26/reflection.md">
<span class="fa fa-fw fa-pencil"></span>編集
</a>
</p>
</div>
</div>
<div class="row">
<div class="col-sm-12 content-body">
<h1 itemprop="name"><span class="token">静的リフレクション [P2996R13]</span><span class="cpp cpp26" title="C++26で追加">(C++26)</span></h1>
<div itemprop="articleBody"><p>
</p>
<p>このページはC++26に採用される見込みの言語機能の変更を解説しています。</p>
<p>のちのC++規格でさらに変更される場合があるため<a href="#relative-page">関連項目</a>を参照してください。</p>
<p>
</p>
<h2>概要</h2>
<p>C++26では、コンパイル時にプログラムの構造を検査・操作できる「静的リフレクション (static reflection)」機能を導入する。</p>
<p>この機能は以下の要素で構成される:</p>
<ul>
<li><strong>リフレクション演算子<code>^^</code></strong> : 型、名前空間、変数、関数、メンバなどのプログラム要素から、その情報を表すコンパイル時の値(リフレクション)を生成する</li>
<li><strong>スプライス演算子<code>[: :]</code></strong> : リフレクションをプログラム要素(型、式、テンプレート引数など)に変換して挿入する</li>
<li><strong><code>std::meta::info</code>型</strong> : リフレクションを表すスカラ型。<a class="cpprefjp-defined-word" data-desc="structural type。定数テンプレートパラメータとして使用できる型の条件。スカラ型、左辺値参照型、すべての基底クラスとメンバ変数がpublicかつmutableでなく構造的型であるリテラルクラス型、および同様の条件を満たす配列型が該当する">構造的型</a> (structural type) であり、<a class="cpprefjp-defined-word" data-desc="constant template parameter。テンプレートパラメータのうち、型ではなく値をとるもの。C++23以前は「非型テンプレートパラメータ (non-type template parameter)」と呼ばれていた">定数テンプレートパラメータ</a>として使用できる</li>
<li><strong><code><meta></code>ヘッダ</strong> : リフレクションを操作するためのメタ関数群を提供する新しいヘッダ</li>
<li><strong><code>consteval</code>ブロック</strong> : <code>consteval { ... }</code>によるコンパイル時副作用の実行</li>
<li><strong>アノテーション</strong> : 宣言にコンパイル時定数を付加し、リフレクションで取得できる機構</li>
<li><strong>関数パラメータのリフレクション</strong> : 関数の仮引数の型、名前、デフォルト引数の有無などをリフレクションで取得できる</li>
</ul>
<p><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../../reference/meta.html"><meta></a></span>
<span class="cp">#include <a href="../../reference/print.html"><print></a></span>
<span class="k">enum</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Color</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">red</span><span class="p">,</span><span class="w"> </span><span class="n">green</span><span class="p">,</span><span class="w"> </span><span class="n">blue</span><span class="w"> </span><span class="p">};</span>
<span class="c1">// 列挙値を文字列に変換する汎用関数</span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="k">typename</span><span class="w"> </span><span class="nc">E</span><span class="o">></span>
<span class="w"> </span><span class="k">requires</span><span class="w"> </span><span class="n"><a href="../../reference/type_traits/is_enum.html">std::is_enum_v</a></span><span class="o"><</span><span class="n">E</span><span class="o">></span>
<span class="k">constexpr</span><span class="w"> </span><span class="n"><a href="../../reference/string_view/basic_string_view.html">std::string_view</a></span><span class="w"> </span><span class="n">to_string</span><span class="p">(</span><span class="n">E</span><span class="w"> </span><span class="n">value</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// 型Eから列挙子のリストを取得</span>
<span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/enumerators_of.html">std::meta::enumerators_of</a></span><span class="p">(</span><span class="o">^^</span><span class="n">E</span><span class="p">)))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">value</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p">[</span><span class="o">:</span><span class="n">e</span><span class="o">:</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n"><a href="../../reference/meta/identifier_of.html">std::meta::identifier_of</a></span><span class="p">(</span><span class="n">e</span><span class="p">);</span><span class="w"> </span><span class="c1">// 列挙子の名前を文字列として取得</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="s">"<unknown>"</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span><span class="w"> </span><span class="n">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">to_string</span><span class="p">(</span><span class="n">Color</span><span class="o">::</span><span class="n">red</span><span class="p">));</span><span class="w"> </span><span class="c1">// "red"</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">to_string</span><span class="p">(</span><span class="n">Color</span><span class="o">::</span><span class="n">green</span><span class="p">));</span><span class="w"> </span><span class="c1">// "green"</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">to_string</span><span class="p">(</span><span class="n">Color</span><span class="o">::</span><span class="n">blue</span><span class="p">));</span><span class="w"> </span><span class="c1">// "blue"</span>
<span class="p">}</span>
</code></pre></div>
</p>
<h2>リフレクション演算子<code>^^</code></h2>
<p><code>^^</code>は前置の単項演算子であり、プログラム要素から<code><a href="../../reference/meta/info.html">std::meta::info</a></code>型の値を生成する。</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">r1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">^^</span><span class="kt">int</span><span class="p">;</span><span class="w"> </span><span class="c1">// 型のリフレクション</span>
<span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">r2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">^^</span><span class="n">std</span><span class="p">;</span><span class="w"> </span><span class="c1">// 名前空間のリフレクション</span>
<span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">r3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">^^::</span><span class="p">;</span><span class="w"> </span><span class="c1">// グローバル名前空間のリフレクション</span>
<span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">r4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">^^</span><span class="n"><a href="../../reference/vector/vector.html">std::vector</a></span><span class="p">;</span><span class="w"> </span><span class="c1">// テンプレートのリフレクション</span>
</code></pre></div>
</p>
<p>リフレクションできる対象と、取得できる主な情報:</p>
<table border="1" bordercolor="#888" style="border-collapse:collapse">
<thead>
<tr>
<th>対象</th>
<th>構文例</th>
<th>取得できる情報</th>
</tr>
</thead>
<tbody>
<tr>
<td>型</td>
<td><code>^^int</code>, <code>^^std::string</code></td>
<td>名前、サイズ、アライメント、型特性、メンバ一覧、基底クラス一覧</td>
</tr>
<tr>
<td>名前空間</td>
<td><code>^^std</code>, <code>^^::</code></td>
<td>名前、メンバ一覧</td>
</tr>
<tr>
<td>変数</td>
<td><code>^^x</code></td>
<td>名前、型、記憶域期間、リンケージ</td>
</tr>
<tr>
<td>関数</td>
<td><code>^^f</code></td>
<td>名前、<a class="cpprefjp-defined-word" data-desc="関数呼び出し式の評価結果となるオブジェクト・値">戻り値</a>型、パラメータ一覧、<code>noexcept</code>の有無</td>
</tr>
<tr>
<td>メンバ変数</td>
<td><code>^^S::m</code></td>
<td>名前、型、オフセット、アクセス指定子、ビットフィールドの有無</td>
</tr>
<tr>
<td>列挙子</td>
<td><code>^^Color::red</code></td>
<td>名前、値、所属する列挙型</td>
</tr>
<tr>
<td>テンプレート</td>
<td><code>^^std::vector</code></td>
<td>名前、テンプレート引数の置換</td>
</tr>
<tr>
<td>基底クラス関係</td>
<td><code><a href="../../reference/meta/bases_of.html">bases_of()</a></code>経由</td>
<td>基底クラスの型、アクセス指定子、<code>virtual</code>の有無</td>
</tr>
<tr>
<td>関数パラメータ</td>
<td><code><a href="../../reference/meta/parameters_of.html">parameters_of()</a></code>経由</td>
<td>名前、型、デフォルト引数の有無、明示的オブジェクトパラメータか</td>
</tr>
<tr>
<td>アノテーション</td>
<td><code><a href="../../reference/meta/annotations_of.html">annotations_of()</a></code>経由</td>
<td>型、値(スプライスで取得)、ソース位置</td>
</tr>
</tbody>
</table>
<h3><a class="cpprefjp-defined-word" data-desc="同名の関数を異なる引数・テンプレート・制約などで複数定義すること。または同名の関数の集合">オーバーロード</a>された関数のリフレクション</h3>
<p><code>^^f</code>で関数<code>f</code>をリフレクションする場合、<code>f</code>が<a class="cpprefjp-defined-word" data-desc="同名の関数を異なる引数・テンプレート・制約などで複数定義すること。または同名の関数の集合">オーバーロード</a>されていると<a class="cpprefjp-defined-word" data-desc="プログラムが適格でないこと。コンパイルエラーなどになる" href="../../implementation-compliance.html#dfn-ill-formed">不適格</a>となる。<code>^^</code>は<a class="cpprefjp-defined-word" data-desc="同名の関数を異なる引数・テンプレート・制約などで複数定義すること。または同名の関数の集合">オーバーロード</a>集合ではなく単一の関数を対象とする。</p>
<p><div class="codehilite"><pre><span></span><code><span class="kt">void</span><span class="w"> </span><span class="nf">f</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">f</span><span class="p">(</span><span class="kt">double</span><span class="p">);</span>
<span class="c1">// constexpr auto r = ^^f; // エラー: fはオーバーロードされている</span>
</code></pre></div>
</p>
<p><a class="cpprefjp-defined-word" data-desc="同名の関数を異なる引数・テンプレート・制約などで複数定義すること。または同名の関数の集合">オーバーロード</a>された関数がクラスのメンバ関数である場合、個々の<a class="cpprefjp-defined-word" data-desc="同名の関数を異なる引数・テンプレート・制約などで複数定義すること。または同名の関数の集合">オーバーロード</a>を取得するには<code><a href="../../reference/meta/members_of.html">members_of()</a></code>を使用する。<code>members_of()</code>は各<a class="cpprefjp-defined-word" data-desc="同名の関数を異なる引数・テンプレート・制約などで複数定義すること。または同名の関数の集合">オーバーロード</a>を個別のリフレクションとして返す。</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">struct</span><span class="w"> </span><span class="nc">S</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">f</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span>
<span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">f</span><span class="p">(</span><span class="kt">double</span><span class="p">);</span>
<span class="p">};</span>
<span class="k">consteval</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// members_of()で個々のオーバーロードを取得</span>
<span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">members</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/members_of.html">std::meta::members_of</a></span><span class="p">(</span>
<span class="w"> </span><span class="o">^^</span><span class="n">S</span><span class="p">,</span><span class="w"> </span><span class="n"><a href="../../reference/meta/access_context.html">std::meta::access_context</a></span><span class="o">::</span><span class="n"><a href="../../reference/meta/access_context/unchecked.html">unchecked</a></span><span class="p">());</span>
<span class="w"> </span><span class="c1">// フィルタリングで特定のオーバーロードを選択できる</span>
<span class="p">}</span>
</code></pre></div>
</p>
<p>非メンバ関数(名前空間スコープの関数)の場合、<a class="cpprefjp-defined-word" data-desc="同名の関数を異なる引数・テンプレート・制約などで複数定義すること。または同名の関数の集合">オーバーロード</a>集合そのものをリフレクションとして取得する手段は存在しない。そのため、非メンバ関数で<a class="cpprefjp-defined-word" data-desc="同名の関数を異なる引数・テンプレート・制約などで複数定義すること。または同名の関数の集合">オーバーロード</a>集合から特定の<a class="cpprefjp-defined-word" data-desc="同名の関数を異なる引数・テンプレート・制約などで複数定義すること。または同名の関数の集合">オーバーロード</a>を扱いたい場合は、関数ポインタ型にキャストして型を明示するなどの手段が必要となる。汎用的に関数の<a class="cpprefjp-defined-word" data-desc="同名の関数を異なる引数・テンプレート・制約などで複数定義すること。または同名の関数の集合">オーバーロード</a>をリフレクションで扱いたい場合は、クラスのメンバ関数として定義することが必要になる。</p>
<p>また、スプライスで関数のリフレクションを式に変換する場合、<a class="cpprefjp-defined-word" data-desc="関数呼び出し時に、同名の関数の中から実際に呼び出す関数を決定する処理。このときの候補になることを、オーバーロード解決に参加するという">オーバーロード解決</a>は行われず、そのリフレクションが表す特定の関数が直接使用される。</p>
<h2>スプライス演算子<code>[: :]</code></h2>
<p>スプライス演算子は、<code><a href="../../reference/meta/info.html">std::meta::info</a></code>型の値(リフレクション)を受け取り、それが表すプログラム要素(型、式、テンプレート、名前空間)に変換して挿入する。<code>[:</code>と<code>:]</code>の間には<code>std::meta::info</code>型に評価される式を記述する。</p>
<p><div class="codehilite"><pre><span></span><code><span class="c1">// 型スプライス:リフレクションが表す型を挿入する</span>
<span class="k">constexpr</span><span class="w"> </span><span class="n"><a href="../../reference/meta/info.html">std::meta::info</a></span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">^^</span><span class="kt">int</span><span class="p">;</span>
<span class="k">typename</span><span class="p">[</span><span class="o">:</span><span class="n">r</span><span class="o">:</span><span class="p">]</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">42</span><span class="p">;</span><span class="w"> </span><span class="c1">// int x = 42; と等価</span>
<span class="c1">// 式スプライス:リフレクションが表す変数や関数を式として挿入する</span>
<span class="kt">int</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">10</span><span class="p">;</span>
<span class="k">constexpr</span><span class="w"> </span><span class="n"><a href="../../reference/meta/info.html">std::meta::info</a></span><span class="w"> </span><span class="n">rv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">^^</span><span class="n">value</span><span class="p">;</span>
<span class="p">[</span><span class="o">:</span><span class="n">rv</span><span class="o">:</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">20</span><span class="p">;</span><span class="w"> </span><span class="c1">// value = 20; と等価</span>
</code></pre></div>
</p>
<p>リフレクションが表す要素の種類に応じて、スプライスの構文が異なる:</p>
<table border="1" bordercolor="#888" style="border-collapse:collapse">
<thead>
<tr>
<th>種類</th>
<th>構文</th>
<th>用途</th>
</tr>
</thead>
<tbody>
<tr>
<td>型スプライス</td>
<td><code>typename[:r:]</code></td>
<td>リフレクション<code>r</code>が表す型を挿入。型のみの文脈では<code>typename</code>を省略可能</td>
</tr>
<tr>
<td>式スプライス</td>
<td><code>[:r:]</code></td>
<td>リフレクション<code>r</code>が表す変数・関数・列挙子などを式として挿入</td>
</tr>
<tr>
<td>テンプレートスプライス</td>
<td><code>template[:r:]</code></td>
<td>リフレクション<code>r</code>が表すテンプレートを挿入</td>
</tr>
<tr>
<td>名前空間スプライス</td>
<td><code>namespace[:r:]</code></td>
<td>リフレクション<code>r</code>が表す名前空間を挿入</td>
</tr>
</tbody>
</table>
<p>変数を表すリフレクションに対する式スプライスは、対応する式と同じ振る舞いをする。たとえば<a class="cpprefjp-defined-word" data-desc="関数等の意味論を構成する要素の1つ。Preconditions。関数呼び出し時に満たされていると関数が想定する条件。満たさなければ未定義の動作。契約属性の`[[expects]]`に相当">事前条件</a>式 (<code>pre</code>) や<a class="cpprefjp-defined-word" data-desc="関数等の意味論を構成する要素の1つ。Postconditions。関数を実行後に満たされている条件。契約属性の`[[ensures]]`に相当">事後条件</a>式 (<code>post</code>) の中の式は自動的に<code>const</code>修飾されるが、式スプライス<code>[:r:]</code>の結果も同様に<code>const</code>修飾される。</p>
<p>メンバアクセスにもスプライスを使用できる。<code>obj.[:r:]</code>の形式で、リフレクション<code>r</code>が表すメンバ変数や基底クラスにアクセスする:</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">struct</span><span class="w"> </span><span class="nc">S</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">;</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">y</span><span class="p">;</span><span class="w"> </span><span class="p">};</span>
<span class="k">consteval</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">example</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">S</span><span class="w"> </span><span class="n">s</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">};</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">members</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/nonstatic_data_members_of.html">std::meta::nonstatic_data_members_of</a></span><span class="p">(</span>
<span class="w"> </span><span class="o">^^</span><span class="n">S</span><span class="p">,</span><span class="w"> </span><span class="n"><a href="../../reference/meta/access_context.html">std::meta::access_context</a></span><span class="o">::</span><span class="n"><a href="../../reference/meta/access_context/unchecked.html">unchecked</a></span><span class="p">()));</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="p">.[</span><span class="o">:</span><span class="n">members</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span><span class="p">];</span><span class="w"> </span><span class="c1">// s.x と等価。a == 1</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="p">.[</span><span class="o">:</span><span class="n">members</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">:</span><span class="p">];</span><span class="w"> </span><span class="c1">// s.y と等価。b == 2</span>
<span class="p">}</span>
</code></pre></div>
</p>
<h3>基底クラスのサブオブジェクトへのスプライス</h3>
<p>基底クラスのリフレクションに対してもメンバアクセスのスプライスを使用できる。これにより、メンバ変数と基底クラスを統一的に扱うことができる。</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">struct</span><span class="w"> </span><span class="nc">Base</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">b</span><span class="p">;</span><span class="w"> </span><span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Derived</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">Base</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">d</span><span class="p">;</span><span class="w"> </span><span class="p">};</span>
<span class="k">consteval</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">example</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Derived</span><span class="w"> </span><span class="n">obj</span><span class="p">{{</span><span class="mi">42</span><span class="p">},</span><span class="w"> </span><span class="mi">100</span><span class="p">};</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">bases</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/bases_of.html">std::meta::bases_of</a></span><span class="p">(</span>
<span class="w"> </span><span class="o">^^</span><span class="n">Derived</span><span class="p">,</span><span class="w"> </span><span class="n"><a href="../../reference/meta/access_context.html">std::meta::access_context</a></span><span class="o">::</span><span class="n"><a href="../../reference/meta/access_context/unchecked.html">unchecked</a></span><span class="p">()));</span>
<span class="w"> </span><span class="n">Base</span><span class="o">&</span><span class="w"> </span><span class="n">base_ref</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">obj</span><span class="p">.[</span><span class="o">:</span><span class="n">bases</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span><span class="p">];</span><span class="w"> </span><span class="c1">// 基底クラスのサブオブジェクトへの参照</span>
<span class="p">}</span>
</code></pre></div>
</p>
<h2><code>std::meta::info</code>型</h2>
<p><code><a href="../../reference/meta/info.html">std::meta::info</a></code>型は、リフレクションを表す基本的な型である。</p>
<ul>
<li><code><a href="../../reference/meta.html"><meta></a></code>ヘッダで<code>using info = decltype(^^::);</code>として定義される。<code>^^::</code>はグローバル名前空間のリフレクションを生成する式であり、<code>decltype</code>でその型を取得している</li>
<li>スカラ型であり、クラス型ではない</li>
<li><code>==</code>と<code>!=</code>をサポートするが、順序比較(<code><</code>, <code>></code>, <code><=></code>)はサポートしない</li>
<li><a class="cpprefjp-defined-word" data-desc="structural type。定数テンプレートパラメータとして使用できる型の条件。スカラ型、左辺値参照型、すべての基底クラスとメンバ変数がpublicかつmutableでなく構造的型であるリテラルクラス型、および同様の条件を満たす配列型が該当する">構造的型</a> (structural type) であり、<a class="cpprefjp-defined-word" data-desc="constant template parameter。テンプレートパラメータのうち、型ではなく値をとるもの。C++23以前は「非型テンプレートパラメータ (non-type template parameter)」と呼ばれていた">定数テンプレートパラメータ</a>として使用できる</li>
<li>consteval-only型であり、実行時には存在できない<ul>
<li>C++29 : consteval-only型の規則は、<a href="../cpp29/consteval-only_values.html">consteval-only値にもとづく規則へ置き換えられた</a>。ヌルリフレクションのみを保持する<code>info</code>オブジェクトは実行時にも存在できる</li>
</ul>
</li>
</ul>
<p><div class="codehilite"><pre><span></span><code><span class="c1">// 定数テンプレートパラメータとして使用する例</span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="n"><a href="../../reference/meta/info.html">std::meta::info</a></span><span class="w"> </span><span class="n">R</span><span class="o">></span>
<span class="k">using</span><span class="w"> </span><span class="n">type_of_reflection</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">typename</span><span class="p">[</span><span class="o">:</span><span class="n">R</span><span class="o">:</span><span class="p">];</span>
<span class="n">type_of_reflection</span><span class="o"><^^</span><span class="kt">int</span><span class="o">></span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">42</span><span class="p">;</span><span class="w"> </span><span class="c1">// int x = 42;</span>
</code></pre></div>
</p>
<p>2つのリフレクションは、同じエンティティを反映している場合に等値となる。型の別名は、元の型とは区別される:</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">using</span><span class="w"> </span><span class="n">MyInt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kt">int</span><span class="p">;</span>
<span class="k">static_assert</span><span class="p">(</span><span class="o">^^</span><span class="kt">int</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="o">^^</span><span class="n">MyInt</span><span class="p">);</span><span class="w"> </span><span class="c1">// 型の別名は区別される</span>
<span class="k">static_assert</span><span class="p">(</span><span class="o">^^</span><span class="kt">int</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n"><a href="../../reference/meta/dealias.html">std::meta::dealias</a></span><span class="p">(</span><span class="o">^^</span><span class="n">MyInt</span><span class="p">));</span><span class="w"> </span><span class="c1">// dealias()で元の型を取得</span>
</code></pre></div>
</p>
<h2><code><meta></code>ヘッダのメタ関数</h2>
<p><code><a href="../../reference/meta.html"><meta></a></code>ヘッダは、リフレクションを操作するための多数の<code>consteval</code>メタ関数を提供する。名前の取得、エンティティの分類・検査、メンバや基底クラスの列挙、型特性の判定と型変換、テンプレート操作、レイアウト情報の取得、集成体型の動的定義など、広範な機能を備える。</p>
<p>詳細は<a href="../../reference/meta.html"><code><meta></code>ヘッダのリファレンス</a>を参照。</p>
<h2><code>consteval</code>ブロック</h2>
<p><code>consteval { ... }</code>構文により、コンパイル時に副作用のあるコードを実行できる。<code><a href="../../reference/meta/define_aggregate.html">std::meta::define_aggregate()</a></code>と組み合わせて型を動的に生成する際に使用する。</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">struct</span><span class="w"> </span><span class="nc">S</span><span class="p">;</span>
<span class="k">consteval</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// Sを2つのintメンバを持つ集成体として定義</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/define_aggregate.html">std::meta::define_aggregate</a></span><span class="p">(</span><span class="o">^^</span><span class="n">S</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/data_member_spec.html">std::meta::data_member_spec</a></span><span class="p">(</span><span class="o">^^</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="p">{.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"x"</span><span class="p">}),</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/data_member_spec.html">std::meta::data_member_spec</a></span><span class="p">(</span><span class="o">^^</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="p">{.</span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"y"</span><span class="p">})</span>
<span class="w"> </span><span class="p">});</span>
<span class="p">}</span>
<span class="n">S</span><span class="w"> </span><span class="n">s</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">};</span><span class="w"> </span><span class="c1">// s.x == 1, s.y == 2</span>
</code></pre></div>
</p>
<h2>アノテーション</h2>
<p>宣言にコンパイル時定数値を付加し、リフレクションで取得できる機構である。属性とは異なり、<a class="cpprefjp-defined-word" data-desc="プログラム定義。ユーザー(プログラマ)によって定義されること(標準ライブラリで定義されるものを除く)">ユーザー定義</a>の意味的データを運ぶ。</p>
<h3>構文</h3>
<p><code>[[=定数式]]</code>の構文でアノテーションを付加する。<code>=</code>接頭辞により通常の属性と区別される。</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">struct</span><span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="mi">1</span><span class="p">]]</span><span class="w"> </span><span class="n">Annotated</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="o">=</span><span class="mi">24</span><span class="p">]]</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">value</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div>
</p>
<p>アノテーションの式は<a class="cpprefjp-defined-word" data-desc="structural type。定数テンプレートパラメータとして使用できる型の条件。スカラ型、左辺値参照型、すべての基底クラスとメンバ変数がpublicかつmutableでなく構造的型であるリテラルクラス型、および同様の条件を満たす配列型が該当する">構造的型</a>でなければならない。アノテーションの取得には<code><a href="../../reference/meta/annotations_of.html">annotations_of()</a></code>や<code><a href="../../reference/meta/annotations_of_with_type.html">annotations_of_with_type()</a></code>メタ関数を使用する。</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">struct</span><span class="w"> </span><span class="nc">Name</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="n">value</span><span class="p">;</span><span class="w"> </span><span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">Name</span><span class="p">{</span><span class="n"><a href="../../reference/meta/define_static_string.html">std::define_static_string</a></span><span class="p">(</span><span class="s">"点"</span><span class="p">)}]]</span><span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">Name</span><span class="p">{</span><span class="n"><a href="../../reference/meta/define_static_string.html">std::define_static_string</a></span><span class="p">(</span><span class="s">"x座標"</span><span class="p">)}]]</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
<span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">Name</span><span class="p">{</span><span class="n"><a href="../../reference/meta/define_static_string.html">std::define_static_string</a></span><span class="p">(</span><span class="s">"y座標"</span><span class="p">)}]]</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">y</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">// メンバのアノテーションを取得</span>
<span class="k">template</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">:</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/nonstatic_data_members_of.html">std::meta::nonstatic_data_members_of</a></span><span class="p">(</span><span class="o">^^</span><span class="n">Point</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/access_context.html">std::meta::access_context</a></span><span class="o">::</span><span class="n"><a href="../../reference/meta/access_context/unchecked.html">unchecked</a></span><span class="p">())))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">annots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/annotations_of_with_type.html">std::meta::annotations_of_with_type</a></span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="o">^^</span><span class="n">Name</span><span class="p">));</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="p">(</span><span class="n">annots</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// アノテーションは値のリフレクションではないため、</span>
<span class="w"> </span><span class="c1">// constant_of()で値を取り出してからスプライスする</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"{}: {}"</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="o">:</span><span class="n"><a href="../../reference/meta/constant_of.html">std::meta::constant_of</a></span><span class="p">(</span><span class="n">annots</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="o">:</span><span class="p">].</span><span class="n">value</span><span class="p">,</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">meta</span><span class="o">::</span><span class="n">identifier_of</span><span class="p">(</span><span class="n">m</span><span class="p">));</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="c1">// 出力:</span>
<span class="c1">// x座標: x</span>
<span class="c1">// y座標: y</span>
</code></pre></div>
</p>
<h2><code>define_static_string</code> / <code>define_static_array</code> / <code>define_static_object</code></h2>
<p>これらは、コンパイル時に計算した値を静的ストレージに配置し、実行時に使用可能にするための関数群である。これらは<code><meta></code>ヘッダで提供されるが、<code>std</code>名前空間に定義される(<code>std::meta</code>名前空間ではない)。</p>
<table border="1" bordercolor="#888" style="border-collapse:collapse">
<thead>
<tr>
<th>関数</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code><a href="../../reference/meta/define_static_string.html">std::define_static_string()</a></code></td>
<td>コンパイル時文字列を静的ストレージに配置し、<a class="cpprefjp-defined-word" data-desc="null-terminated。文字列においてヌル文字 '\0' を用いてその終端を表すこと。ヌル文字自体は文字列に含まない。広義には線形データ構造においてヌルまたは値 0 を番兵としてその終わりを示すこと">ヌル終端</a>の<code>const CharT*</code>を返す</td>
</tr>
<tr>
<td><code><a href="../../reference/meta/define_static_array.html">std::define_static_array()</a></code></td>
<td>コンパイル時配列を静的ストレージに配置し、<code><a href="../../reference/span/span.html">std::span</a><const T></code>を返す</td>
</tr>
<tr>
<td><code><a href="../../reference/meta/define_static_object.html">std::define_static_object()</a></code></td>
<td>コンパイル時オブジェクトを静的ストレージに配置し、<code>const T*</code>を返す</td>
</tr>
</tbody>
</table>
<h3>主な用途</h3>
<p>これらの関数は、以下のようなリフレクションの典型的なユースケースで頻繁に使用される。</p>
<h4>(1) <code>template for</code>文のrangeを静的配列に変換する</h4>
<p><code><a href="../../reference/meta/members_of.html">members_of()</a></code>や<code><a href="../../reference/meta/enumerators_of.html">enumerators_of()</a></code>などのメタ関数は<code>std::vector<std::meta::info></code>を返すが、<code>std::vector</code>は動的メモリ確保を伴うため<a href="expansion_statements.html"><code>template for</code>文</a>のrangeとして直接使用できない。<code><a href="../../reference/meta/define_static_array.html">std::define_static_array()</a></code>で静的ストレージに配置した<code><a href="../../reference/span/span.html">std::span</a></code>に変換することで、<code>template for</code>文で走査できるようになる。</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">template</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">:</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/nonstatic_data_members_of.html">std::meta::nonstatic_data_members_of</a></span><span class="p">(</span><span class="o">^^</span><span class="n">S</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/access_context/unchecked.html">std::meta::access_context::unchecked</a></span><span class="p">())))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// mを使った処理</span>
<span class="p">}</span>
</code></pre></div>
</p>
<h4>(2) コンパイル時文字列を実行時に返す</h4>
<p>コンパイル時に構築した<code><a href="../../reference/string/basic_string.html">std::string</a></code>や<code><a href="../../reference/string_view/basic_string_view.html">std::string_view</a></code>は、そのままでは実行時にアクセスできない(一時オブジェクトの寿命が尽きる、または<code>consteval</code>型の制約)。<code><a href="../../reference/meta/define_static_string.html">std::define_static_string()</a></code>で静的ストレージに配置することで、<a class="cpprefjp-defined-word" data-desc="null-terminated。文字列においてヌル文字 '\0' を用いてその終端を表すこと。ヌル文字自体は文字列に含まない。広義には線形データ構造においてヌルまたは値 0 を番兵としてその終わりを示すこと">ヌル終端</a>の<code>const char*</code>として実行時まで持ち越せる。</p>
<p>ただし、<code><a href="../../reference/meta/identifier_of.html">identifier_of()</a></code>のように既に<code>string_view</code>を返す関数は、そのまま<a class="cpprefjp-defined-word" data-desc="関数呼び出し式の評価結果となるオブジェクト・値">戻り値</a>として返せる場合もある(静的ストレージに存在する識別子の文字列を指すため)。</p>
<h4>(3) アノテーションの文字列リテラル</h4>
<p>アノテーションの式は<a class="cpprefjp-defined-word" data-desc="structural type。定数テンプレートパラメータとして使用できる型の条件。スカラ型、左辺値参照型、すべての基底クラスとメンバ変数がpublicかつmutableでなく構造的型であるリテラルクラス型、および同様の条件を満たす配列型が該当する">構造的型</a>でなければならず、文字列リテラルを直接メンバとして持つと寿命の問題が生じる可能性がある。<code><a href="../../reference/meta/define_static_string.html">std::define_static_string()</a></code>で静的ストレージに配置することで、安全に<code>const char*</code>メンバに格納できる。</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">struct</span><span class="w"> </span><span class="nc">Name</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="n">value</span><span class="p">;</span><span class="w"> </span><span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">Name</span><span class="p">{</span><span class="n"><a href="../../reference/meta/define_static_string.html">std::define_static_string</a></span><span class="p">(</span><span class="s">"ラベル"</span><span class="p">)}]]</span><span class="w"> </span><span class="n">Tagged</span><span class="w"> </span><span class="p">{};</span>
</code></pre></div>
</p>
<h4>(4) コンパイル時に構築したオブジェクトを実行時に参照する</h4>
<p>コンパイル時に構築した任意のオブジェクトを静的ストレージに配置し、実行時にポインタで参照するには<code><a href="../../reference/meta/define_static_object.html">std::define_static_object()</a></code>を使用する。</p>
<p><div class="codehilite"><pre><span></span><code><span class="k">struct</span><span class="w"> </span><span class="nc">Config</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">width</span><span class="p">;</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">height</span><span class="p">;</span><span class="w"> </span><span class="p">};</span>
<span class="c1">// コンパイル時に構築したConfigオブジェクトを静的ストレージに配置</span>
<span class="k">constexpr</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">Config</span><span class="o">*</span><span class="w"> </span><span class="n">config</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_object.html">std::define_static_object</a></span><span class="p">(</span><span class="n">Config</span><span class="p">{</span><span class="mi">1920</span><span class="p">,</span><span class="w"> </span><span class="mi">1080</span><span class="p">});</span>
</code></pre></div>
</p>
<h2>リフレクションのエラー処理</h2>
<p>リフレクションのメタ関数は、不正な入力に対して<code><a href="../../reference/meta/exception.html">std::meta::exception</a></code>を送出する。定数評価中の<a class="cpprefjp-defined-word" data-desc="問題が発生したときに、現在実行位置を過去に通過・記録した位置に戻し、文脈情報を添えて紐づけられた処理(例外ハンドラー)を呼び出す仕組み。またはその事態">例外</a>処理として動作するため、実行時のオーバーヘッドはない。</p>
<h2>例</h2>
<h3>構造体のメンバを列挙する</h3>
<p><div class="yata" id="dc713454112d0f6457b061ff4f904f2d28f4f1a3"><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../../reference/meta.html"><meta></a></span>
<span class="cp">#include <a href="../../reference/print.html"><print></a></span>
<span class="cp">#include <a href="../../reference/string.html"><string></a></span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Point</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">y</span><span class="p">;</span>
<span class="w"> </span><span class="n"><a href="../../reference/string/basic_string.html">std::string</a></span><span class="w"> </span><span class="n">name</span><span class="p">;</span>
<span class="p">};</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Point</span><span class="w"> </span><span class="n">p</span><span class="p">{</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="mi">20</span><span class="p">,</span><span class="w"> </span><span class="s">"origin"</span><span class="p">};</span>
<span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">:</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/nonstatic_data_members_of.html">std::meta::nonstatic_data_members_of</a></span><span class="p">(</span><span class="o">^^</span><span class="n">Point</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/access_context.html">std::meta::access_context</a></span><span class="o">::</span><span class="n"><a href="../../reference/meta/access_context/unchecked.html">unchecked</a></span><span class="p">())))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"{}: {}"</span><span class="p">,</span><span class="w"> </span><span class="n"><a href="../../reference/meta/identifier_of.html">std::meta::identifier_of</a></span><span class="p">(</span><span class="n">m</span><span class="p">),</span><span class="w"> </span><span class="n">p</span><span class="p">.[</span><span class="o">:</span><span class="n">m</span><span class="o">:</span><span class="p">]);</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
</div></p>
<h4>出力</h4>
<p><pre><code>x: 10
y: 20
name: origin
</code></pre></p>
<h3>列挙値を文字列に変換する</h3>
<p><div class="yata" id="1d0e5e701108bc287a38e926f0274b36ce3c7637"><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../../reference/meta.html"><meta></a></span>
<span class="cp">#include <a href="../../reference/print.html"><print></a></span>
<span class="cp">#include <a href="../../reference/string_view.html"><string_view></a></span>
<span class="cp">#include <a href="../../reference/type_traits.html"><type_traits></a></span>
<span class="k">enum</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Color</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">red</span><span class="p">,</span><span class="w"> </span><span class="n">green</span><span class="p">,</span><span class="w"> </span><span class="n">blue</span><span class="w"> </span><span class="p">};</span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="k">typename</span><span class="w"> </span><span class="nc">E</span><span class="o">></span>
<span class="w"> </span><span class="k">requires</span><span class="w"> </span><span class="n"><a href="../../reference/type_traits/is_enum.html">std::is_enum_v</a></span><span class="o"><</span><span class="n">E</span><span class="o">></span>
<span class="k">constexpr</span><span class="w"> </span><span class="n"><a href="../../reference/string_view/basic_string_view.html">std::string_view</a></span><span class="w"> </span><span class="n">to_string</span><span class="p">(</span><span class="n">E</span><span class="w"> </span><span class="n">value</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/enumerators_of.html">std::meta::enumerators_of</a></span><span class="p">(</span><span class="o">^^</span><span class="n">E</span><span class="p">)))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">value</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p">[</span><span class="o">:</span><span class="n">e</span><span class="o">:</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n"><a href="../../reference/meta/identifier_of.html">std::meta::identifier_of</a></span><span class="p">(</span><span class="n">e</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="s">"<unknown>"</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span><span class="w"> </span><span class="n">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">to_string</span><span class="p">(</span><span class="n">Color</span><span class="o">::</span><span class="n">red</span><span class="p">));</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">to_string</span><span class="p">(</span><span class="n">Color</span><span class="o">::</span><span class="n">green</span><span class="p">));</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">to_string</span><span class="p">(</span><span class="n">Color</span><span class="o">::</span><span class="n">blue</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div>
</div></p>
<h4>出力</h4>
<p><pre><code>red
green
blue
</code></pre></p>
<h3>関数パラメータの名前と型を列挙する</h3>
<p><div class="yata" id="debfb987ba31357c31e59a06c81bbfcef765290d"><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../../reference/meta.html"><meta></a></span>
<span class="cp">#include <a href="../../reference/print.html"><print></a></span>
<span class="kt">void</span><span class="w"> </span><span class="nf">process</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="n">name</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/parameters_of.html">std::meta::parameters_of</a></span><span class="p">(</span><span class="o">^^</span><span class="n">process</span><span class="p">)))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"パラメータ: {} (型: {})"</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/identifier_of.html">std::meta::identifier_of</a></span><span class="p">(</span><span class="n">p</span><span class="p">),</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/display_string_of.html">std::meta::display_string_of</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/type_of.html">std::meta::type_of</a></span><span class="p">(</span><span class="n">p</span><span class="p">)));</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
</div></p>
<h4>出力</h4>
<p><pre><code>パラメータ: id (型: int)
パラメータ: value (型: double)
パラメータ: name (型: const char*)
</code></pre></p>
<h3>任意の型のハッシュ値を自動で求める</h3>
<p>リフレクションを使うことで、任意のクラス型に対する汎用的なハッシュ関数を実装できる。以下の例では以下の方針で実装する:</p>
<ul>
<li><code><a href="../../reference/functional/hash.html">std::hash</a><T></code>が特殊化されていればそれを使う</li>
<li>特殊化されていない場合は、クラスのすべてのメンバ変数に対して再帰的にハッシュ値を計算しXORで合成する</li>
</ul>
<p>これにより、ネストしたクラス型に対しても自動的にハッシュ値を計算できる。</p>
<p><div class="yata" id="cc4705aa3432d48637c425007ea1cf6cb1965a67"><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../../reference/meta.html"><meta></a></span>
<span class="cp">#include <a href="../../reference/functional.html"><functional></a></span>
<span class="cp">#include <a href="../../reference/string.html"><string></a></span>
<span class="cp">#include <a href="../../reference/print.html"><print></a></span>
<span class="cp">#include <a href="../../reference/concepts.html"><concepts></a></span>
<span class="cp">#include <a href="../../reference/cstddef.html"><cstddef></a></span>
<span class="c1">// <a href="../../reference/functional/hash.html">std::hash</a><T>が使用可能かを判定するコンセプト</span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">></span>
<span class="k">concept</span><span class="w"> </span><span class="nc">has_std_hash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">requires</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n"><a href="../../reference/functional/hash.html">std::hash</a></span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">{}(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n"><a href="../../reference/concepts/convertible_to.html">std::convertible_to</a></span><span class="o"><</span><span class="n"><a href="../../reference/cstddef/size_t.html">std::size_t</a></span><span class="o">></span><span class="p">;</span>
<span class="p">};</span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">></span>
<span class="k">constexpr</span><span class="w"> </span><span class="n"><a href="../../reference/cstddef/size_t.html">std::size_t</a></span><span class="w"> </span><span class="n">hash_value</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&</span><span class="w"> </span><span class="n">obj</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="p">(</span><span class="n">has_std_hash</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// <a href="../../reference/functional/hash.html">std::hash</a>が特殊化されていれば利用する</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n"><a href="../../reference/functional/hash.html">std::hash</a></span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">{}(</span><span class="n">obj</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// 特殊化されていなければ、各メンバのハッシュ値を再帰的に計算してXORで合成</span>
<span class="w"> </span><span class="n"><a href="../../reference/cstddef/size_t.html">std::size_t</a></span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">:</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/nonstatic_data_members_of.html">std::meta::nonstatic_data_members_of</a></span><span class="p">(</span><span class="o">^^</span><span class="n">T</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/access_context/unchecked.html">std::meta::access_context::unchecked</a></span><span class="p">())))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">^=</span><span class="w"> </span><span class="n">hash_value</span><span class="p">(</span><span class="n">obj</span><span class="p">.[</span><span class="o">:</span><span class="n">m</span><span class="o">:</span><span class="p">]);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Inner</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="p">;</span>
<span class="w"> </span><span class="n"><a href="../../reference/string/basic_string.html">std::string</a></span><span class="w"> </span><span class="n">b</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Outer</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
<span class="w"> </span><span class="n">Inner</span><span class="w"> </span><span class="n">inner</span><span class="p">;</span><span class="w"> </span><span class="c1">// ネストしたクラス型も再帰的にハッシュ化される</span>
<span class="p">};</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Outer</span><span class="w"> </span><span class="n">o1</span><span class="p">{</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="s">"hello"</span><span class="p">}};</span>
<span class="w"> </span><span class="n">Outer</span><span class="w"> </span><span class="n">o2</span><span class="p">{</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="s">"hello"</span><span class="p">}};</span>
<span class="w"> </span><span class="n">Outer</span><span class="w"> </span><span class="n">o3</span><span class="p">{</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="s">"hello"</span><span class="p">}};</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"hash(o1) == hash(o2): {}"</span><span class="p">,</span><span class="w"> </span><span class="n">hash_value</span><span class="p">(</span><span class="n">o1</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">hash_value</span><span class="p">(</span><span class="n">o2</span><span class="p">));</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"hash(o1) == hash(o3): {}"</span><span class="p">,</span><span class="w"> </span><span class="n">hash_value</span><span class="p">(</span><span class="n">o1</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">hash_value</span><span class="p">(</span><span class="n">o3</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div>
</div></p>
<h4>出力</h4>
<p><pre><code>hash(o1) == hash(o2): true
hash(o1) == hash(o3): false
</code></pre></p>
<h3>アノテーションで指定した値の範囲を検証する</h3>
<p>アノテーションでメンバ変数に制約を付加しておくことで、メンバごとに検証コードを書くことなく、任意のクラスに対して働く汎用の検証関数を実装できる。</p>
<p>以下の例では、整数用の<code>IntRange</code>と浮動小数点数用の<code>FloatRange</code>を定義し、それらが付加されたメンバ変数だけを検証して、範囲外であれば<code><a href="../../reference/stdexcept/out_of_range.html">std::out_of_range</a></code><a class="cpprefjp-defined-word" data-desc="問題が発生したときに、現在実行位置を過去に通過・記録した位置に戻し、文脈情報を添えて紐づけられた処理(例外ハンドラー)を呼び出す仕組み。またはその事態">例外</a>を送出する。アノテーションが付いていないメンバ変数は検証の対象にならない。</p>
<p><div class="yata" id="bdb11c56867858a5ff6a07550d64fcac41d41802"><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../../reference/meta.html"><meta></a></span>
<span class="cp">#include <a href="../../reference/cstdio.html"><cstdio></a></span>
<span class="cp">#include <a href="../../reference/format.html"><format></a></span>
<span class="cp">#include <a href="../../reference/print.html"><print></a></span>
<span class="cp">#include <a href="../../reference/stdexcept.html"><stdexcept></a></span>
<span class="cp">#include <a href="../../reference/string_view.html"><string_view></a></span>
<span class="c1">// 値の範囲を表すアノテーションクラス</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">IntRange</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">min_value</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">max_value</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">FloatRange</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">min_value</span><span class="p">;</span>
<span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">max_value</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Config</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">IntRange</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">65535</span><span class="p">}]]</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">port</span><span class="p">;</span>
<span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">IntRange</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">300</span><span class="p">}]]</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">timeout_seconds</span><span class="p">;</span>
<span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">FloatRange</span><span class="p">{</span><span class="mf">0.0</span><span class="p">,</span><span class="w"> </span><span class="mf">1.0</span><span class="p">}]]</span><span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">sampling_rate</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">retry_count</span><span class="p">;</span><span class="w"> </span><span class="c1">// アノテーションがないメンバ変数は検証しない</span>
<span class="p">};</span>
<span class="c1">// IntRangeとFloatRangeのどちらにも使える検証処理</span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="k">class</span><span class="w"> </span><span class="nc">R</span><span class="p">,</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">></span>
<span class="kt">void</span><span class="w"> </span><span class="n">check_range</span><span class="p">(</span><span class="n"><a href="../../reference/string_view/basic_string_view.html">std::string_view</a></span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="w"> </span><span class="n"><a href="../../reference/ranges/range.html">range</a></span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">value</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n"><a href="../../reference/ranges/range.html">range</a></span><span class="p">.</span><span class="n">min_value</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n"><a href="../../reference/ranges/range.html">range</a></span><span class="p">.</span><span class="n">max_value</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">value</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="n"><a href="../../reference/stdexcept/out_of_range.html">std::out_of_range</a></span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/format/format.html">std::format</a></span><span class="p">(</span><span class="s">"{}: {}は{}以上{}以下でなければならない"</span><span class="p">,</span>
<span class="w"> </span><span class="n">name</span><span class="p">,</span>
<span class="w"> </span><span class="n">value</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/ranges/range.html">range</a></span><span class="p">.</span><span class="n">min_value</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/ranges/range.html">range</a></span><span class="p">.</span><span class="n">max_value</span><span class="p">)};</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="c1">// 範囲のアノテーションが付加されたメンバ変数の値を検証する</span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">></span>
<span class="kt">void</span><span class="w"> </span><span class="n">validate</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&</span><span class="w"> </span><span class="n">obj</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">:</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/nonstatic_data_members_of.html">std::meta::nonstatic_data_members_of</a></span><span class="p">(</span><span class="o">^^</span><span class="n">T</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/access_context/unchecked.html">std::meta::access_context::unchecked</a></span><span class="p">())))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">int_annotations</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/annotations_of_with_type.html">std::meta::annotations_of_with_type</a></span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="o">^^</span><span class="n">IntRange</span><span class="p">));</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">float_annotations</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/annotations_of_with_type.html">std::meta::annotations_of_with_type</a></span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="o">^^</span><span class="n">FloatRange</span><span class="p">));</span>
<span class="w"> </span><span class="c1">// アノテーションは値のリフレクションではないため、</span>
<span class="w"> </span><span class="c1">// constant_of()で値を取り出してからスプライスする</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="p">(</span><span class="n">int_annotations</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">check_range</span><span class="p">(</span><span class="n"><a href="../../reference/meta/identifier_of.html">std::meta::identifier_of</a></span><span class="p">(</span><span class="n">m</span><span class="p">),</span><span class="w"> </span><span class="n">obj</span><span class="p">.[</span><span class="o">:</span><span class="n">m</span><span class="o">:</span><span class="p">],</span>
<span class="w"> </span><span class="p">[</span><span class="o">:</span><span class="n"><a href="../../reference/meta/constant_of.html">std::meta::constant_of</a></span><span class="p">(</span><span class="n">int_annotations</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="o">:</span><span class="p">]);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="p">(</span><span class="n">float_annotations</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">check_range</span><span class="p">(</span><span class="n"><a href="../../reference/meta/identifier_of.html">std::meta::identifier_of</a></span><span class="p">(</span><span class="n">m</span><span class="p">),</span><span class="w"> </span><span class="n">obj</span><span class="p">.[</span><span class="o">:</span><span class="n">m</span><span class="o">:</span><span class="p">],</span>
<span class="w"> </span><span class="p">[</span><span class="o">:</span><span class="n"><a href="../../reference/meta/constant_of.html">std::meta::constant_of</a></span><span class="p">(</span><span class="n">float_annotations</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="o">:</span><span class="p">]);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="kt">int</span><span class="w"> </span><span class="n">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// すべて範囲内なので、例外は送出されない</span>
<span class="w"> </span><span class="n">validate</span><span class="p">(</span><span class="n">Config</span><span class="p">{</span>
<span class="w"> </span><span class="p">.</span><span class="n">port</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">8080</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">timeout_seconds</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">30</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">sampling_rate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">retry_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">3</span>
<span class="w"> </span><span class="p">});</span>
<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// portが範囲外</span>
<span class="w"> </span><span class="n">validate</span><span class="p">(</span><span class="n">Config</span><span class="p">{</span>
<span class="w"> </span><span class="p">.</span><span class="n">port</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">timeout_seconds</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">30</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">sampling_rate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.5</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">retry_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">3</span>
<span class="w"> </span><span class="p">});</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n"><a href="../../reference/stdexcept/out_of_range.html">std::out_of_range</a></span><span class="o">&</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="n"><a href="../../reference/cstdio/stderr.html">stderr</a></span><span class="p">,</span><span class="w"> </span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">e</span><span class="p">.</span><span class="n">what</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// sampling_rateが範囲外</span>
<span class="w"> </span><span class="n">validate</span><span class="p">(</span><span class="n">Config</span><span class="p">{</span>
<span class="w"> </span><span class="p">.</span><span class="n">port</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">8080</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">timeout_seconds</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">30</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">sampling_rate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1.5</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">retry_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">3</span>
<span class="w"> </span><span class="p">});</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n"><a href="../../reference/stdexcept/out_of_range.html">std::out_of_range</a></span><span class="o">&</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="n"><a href="../../reference/cstdio/stderr.html">stderr</a></span><span class="p">,</span><span class="w"> </span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">e</span><span class="p">.</span><span class="n">what</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
</div></p>
<h4>出力</h4>
<p><pre><code>port: 0は1以上65535以下でなければならない
sampling_rate: 1.5は0以上1以下でなければならない
</code></pre></p>
<h3>アノテーションからコマンドラインオプションを解析する</h3>
<p>アノテーションはメンバ変数の検証だけでなく、宣言からコードを生成する用途にも使える。以下の例では、Rustの<a href="https://docs.rs/clap/" target="_blank">clap</a>のように、コマンドラインオプションの短縮名と説明をアノテーションでメンバ変数に付加し、そこからヘルプメッセージの生成と引数の解析の両方を行う。</p>
<p>オプションを追加したいときは<code>Args</code>にメンバ変数とアノテーションを足すだけでよく、ヘルプメッセージと解析処理のどちらにも手を入れる必要がない。</p>
<p><div class="yata" id="dda32638040f23bdbb6ad2454f0e3c735535df95"><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../../reference/meta.html"><meta></a></span>
<span class="cp">#include <a href="../../reference/format.html"><format></a></span>
<span class="cp">#include <a href="../../reference/print.html"><print></a></span>
<span class="cp">#include <a href="../../reference/stdexcept.html"><stdexcept></a></span>
<span class="cp">#include <a href="../../reference/string.html"><string></a></span>
<span class="cp">#include <a href="../../reference/string_view.html"><string_view></a></span>
<span class="c1">// オプションの短縮名を表すアノテーション</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Short</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">name</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">// オプションの説明を表すアノテーション</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Help</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="n">text</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Args</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">Short</span><span class="p">{</span><span class="sc">'n'</span><span class="p">},</span><span class="w"> </span><span class="o">=</span><span class="n">Help</span><span class="p">{</span><span class="n"><a href="../../reference/meta/define_static_string.html">std::define_static_string</a></span><span class="p">(</span><span class="s">"挨拶する相手の名前"</span><span class="p">)}]]</span>
<span class="w"> </span><span class="n"><a href="../../reference/string/basic_string.html">std::string</a></span><span class="w"> </span><span class="n">name</span><span class="p">;</span>
<span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">Short</span><span class="p">{</span><span class="sc">'c'</span><span class="p">},</span><span class="w"> </span><span class="o">=</span><span class="n">Help</span><span class="p">{</span><span class="n"><a href="../../reference/meta/define_static_string.html">std::define_static_string</a></span><span class="p">(</span><span class="s">"挨拶を繰り返す回数"</span><span class="p">)}]]</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="p">};</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">assign</span><span class="p">(</span><span class="n"><a href="../../reference/string/basic_string.html">std::string</a></span><span class="o">&</span><span class="w"> </span><span class="n">member</span><span class="p">,</span><span class="w"> </span><span class="n"><a href="../../reference/string_view/basic_string_view.html">std::string_view</a></span><span class="w"> </span><span class="n">value</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">member</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">value</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">assign</span><span class="p">(</span><span class="kt">int</span><span class="o">&</span><span class="w"> </span><span class="n">member</span><span class="p">,</span><span class="w"> </span><span class="n"><a href="../../reference/string_view/basic_string_view.html">std::string_view</a></span><span class="w"> </span><span class="n">value</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">member</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/string/stoi.html">std::stoi</a></span><span class="p">(</span><span class="n"><a href="../../reference/string/basic_string.html">std::string</a></span><span class="p">{</span><span class="n">value</span><span class="p">});</span>
<span class="p">}</span>
<span class="c1">// アノテーションからヘルプメッセージを生成する</span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">></span>
<span class="kt">void</span><span class="w"> </span><span class="n">print_help</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"オプション:"</span><span class="p">);</span>
<span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">:</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/nonstatic_data_members_of.html">std::meta::nonstatic_data_members_of</a></span><span class="p">(</span><span class="o">^^</span><span class="n">T</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/access_context/unchecked.html">std::meta::access_context::unchecked</a></span><span class="p">())))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">shorts</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/annotations_of_with_type.html">std::meta::annotations_of_with_type</a></span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="o">^^</span><span class="n">Short</span><span class="p">));</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">helps</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/annotations_of_with_type.html">std::meta::annotations_of_with_type</a></span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="o">^^</span><span class="n">Help</span><span class="p">));</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">" -{}, --{:<8} {}"</span><span class="p">,</span>
<span class="w"> </span><span class="p">[</span><span class="o">:</span><span class="n"><a href="../../reference/meta/constant_of.html">std::meta::constant_of</a></span><span class="p">(</span><span class="n">shorts</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="o">:</span><span class="p">].</span><span class="n">name</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/identifier_of.html">std::meta::identifier_of</a></span><span class="p">(</span><span class="n">m</span><span class="p">),</span>
<span class="w"> </span><span class="p">[</span><span class="o">:</span><span class="n"><a href="../../reference/meta/constant_of.html">std::meta::constant_of</a></span><span class="p">(</span><span class="n">helps</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="o">:</span><span class="p">].</span><span class="n">text</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="c1">// アノテーションをもとにコマンドライン引数を解析する</span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">></span>
<span class="n">T</span><span class="w"> </span><span class="n">parse</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">argc</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="k">const</span><span class="o">*</span><span class="w"> </span><span class="n">argv</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">args</span><span class="p">{};</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">argc</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/string_view/basic_string_view.html">std::string_view</a></span><span class="w"> </span><span class="n">arg</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">argv</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">matched</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">false</span><span class="p">;</span>
<span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">:</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/nonstatic_data_members_of.html">std::meta::nonstatic_data_members_of</a></span><span class="p">(</span><span class="o">^^</span><span class="n">T</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/access_context/unchecked.html">std::meta::access_context::unchecked</a></span><span class="p">())))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">shorts</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/annotations_of_with_type.html">std::meta::annotations_of_with_type</a></span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="o">^^</span><span class="n">Short</span><span class="p">));</span>
<span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n"><a href="../../reference/string_view/basic_string_view.html">std::string_view</a></span><span class="w"> </span><span class="n">long_name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/identifier_of.html">std::meta::identifier_of</a></span><span class="p">(</span><span class="n">m</span><span class="p">);</span>
<span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">short_name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="o">:</span><span class="n"><a href="../../reference/meta/constant_of.html">std::meta::constant_of</a></span><span class="p">(</span><span class="n">shorts</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="o">:</span><span class="p">].</span><span class="n">name</span><span class="p">;</span>
<span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">is_long</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">arg</span><span class="p">.</span><span class="n"><a href="../../reference/string_view/basic_string_view/starts_with.html">starts_with</a></span><span class="p">(</span><span class="s">"--"</span><span class="p">)</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">arg</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">long_name</span><span class="p">;</span>
<span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">is_short</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">arg</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">arg</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="sc">'-'</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">arg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">short_name</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">is_long</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">is_short</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">++</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">argc</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="n"><a href="../../reference/stdexcept/invalid_argument.html">std::invalid_argument</a></span><span class="p">{</span><span class="n"><a href="../../reference/format/format.html">std::format</a></span><span class="p">(</span><span class="s">"{}: 値が指定されていない"</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">)};</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">assign</span><span class="p">(</span><span class="n">args</span><span class="p">.[</span><span class="o">:</span><span class="n">m</span><span class="o">:</span><span class="p">],</span><span class="w"> </span><span class="n">argv</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="w"> </span><span class="n">matched</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">true</span><span class="p">;</span>
<span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">matched</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="n"><a href="../../reference/stdexcept/invalid_argument.html">std::invalid_argument</a></span><span class="p">{</span><span class="n"><a href="../../reference/format/format.html">std::format</a></span><span class="p">(</span><span class="s">"{}: 不明なオプション"</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">)};</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">args</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span><span class="w"> </span><span class="n">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">print_help</span><span class="o"><</span><span class="n">Args</span><span class="o">></span><span class="p">();</span>
<span class="w"> </span><span class="c1">// コマンドライン引数を模したデータ</span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="n">argv</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="s">"greet"</span><span class="p">,</span><span class="w"> </span><span class="s">"--name"</span><span class="p">,</span><span class="w"> </span><span class="s">"wg21"</span><span class="p">,</span><span class="w"> </span><span class="s">"-c"</span><span class="p">,</span><span class="w"> </span><span class="s">"3"</span><span class="p">};</span>
<span class="w"> </span><span class="n">Args</span><span class="w"> </span><span class="n">args</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse</span><span class="o"><</span><span class="n">Args</span><span class="o">></span><span class="p">(</span><span class="mi">5</span><span class="p">,</span><span class="w"> </span><span class="n">argv</span><span class="p">);</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">args</span><span class="p">.</span><span class="n">count</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/print/println.html">std::println</a></span><span class="p">(</span><span class="s">"Hello {}"</span><span class="p">,</span><span class="w"> </span><span class="n">args</span><span class="p">.</span><span class="n">name</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
</div></p>
<h4>出力</h4>
<p><pre><code>オプション:
-n, --name 挨拶する相手の名前
-c, --count 挨拶を繰り返す回数
Hello wg21
Hello wg21
Hello wg21
</code></pre></p>
<h3>JSONにシリアライズする</h3>
<p>リフレクションでメンバ変数を走査すれば、クラスごとにシリアライズ関数を書かなくてもJSONへ変換できる。さらにアノテーションを併用することで、JSON上の表現だけをクラスの定義から制御できる。</p>
<p>以下の例では、キー名を変更する<code>Rename</code>と、シリアライズの対象から外す<code>Skip</code>を定義する。どちらもC++のコード上での使い方には影響せず、JSONへの変換方法だけを指定する。</p>
<p><div class="yata" id="4545275173341dc590e588f8caa32b37dd2755d4"><div class="codehilite"><pre><span></span><code><span class="cp">#include <a href="../../reference/meta.html"><meta></a></span>
<span class="cp">#include <a href="../../reference/concepts.html"><concepts></a></span>
<span class="cp">#include <a href="../../reference/format.html"><format></a></span>
<span class="cp">#include <a href="../../reference/print.html"><print></a></span>
<span class="cp">#include <a href="../../reference/string.html"><string></a></span>
<span class="cp">#include <a href="../../reference/string_view.html"><string_view></a></span>
<span class="c1">// JSONのキー名を変更するアノテーション</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Rename</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="n">name</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">// シリアライズの対象から外すアノテーション</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Skip</span><span class="w"> </span><span class="p">{};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Address</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/string/basic_string.html">std::string</a></span><span class="w"> </span><span class="n">city</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">postal_code</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Person</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">Rename</span><span class="p">{</span><span class="n"><a href="../../reference/meta/define_static_string.html">std::define_static_string</a></span><span class="p">(</span><span class="s">"first name"</span><span class="p">)}]]</span><span class="w"> </span><span class="n"><a href="../../reference/string/basic_string.html">std::string</a></span><span class="w"> </span><span class="n">first</span><span class="p">;</span>
<span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">Rename</span><span class="p">{</span><span class="n"><a href="../../reference/meta/define_static_string.html">std::define_static_string</a></span><span class="p">(</span><span class="s">"last name"</span><span class="p">)}]]</span><span class="w"> </span><span class="n"><a href="../../reference/string/basic_string.html">std::string</a></span><span class="w"> </span><span class="n">last</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">age</span><span class="p">;</span>
<span class="w"> </span><span class="n">Address</span><span class="w"> </span><span class="n">address</span><span class="p">;</span><span class="w"> </span><span class="c1">// ネストしたクラスも再帰的に変換される</span>
<span class="w"> </span><span class="p">[[</span><span class="o">=</span><span class="n">Skip</span><span class="p">{}]]</span><span class="w"> </span><span class="n"><a href="../../reference/string/basic_string.html">std::string</a></span><span class="w"> </span><span class="n">password</span><span class="p">;</span><span class="w"> </span><span class="c1">// シリアライズしない</span>
<span class="p">};</span>
<span class="k">template</span><span class="w"> </span><span class="o"><</span><span class="k">class</span><span class="w"> </span><span class="nc">T</span><span class="o">></span>
<span class="n"><a href="../../reference/string/basic_string.html">std::string</a></span><span class="w"> </span><span class="n">to_json</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&</span><span class="w"> </span><span class="n">value</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="p">(</span><span class="n"><a href="../../reference/concepts/integral.html">std::integral</a></span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n"><a href="../../reference/concepts/floating_point.html">std::floating_point</a></span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n"><a href="../../reference/format/format.html">std::format</a></span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span><span class="w"> </span><span class="n">value</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="p">(</span><span class="n"><a href="../../reference/concepts/convertible_to.html">std::convertible_to</a></span><span class="o"><</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n"><a href="../../reference/string_view/basic_string_view.html">std::string_view</a></span><span class="o">></span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n"><a href="../../reference/format/format.html">std::format</a></span><span class="p">(</span><span class="s">"</span><span class="se">\"</span><span class="s">{}</span><span class="se">\"</span><span class="s">"</span><span class="p">,</span><span class="w"> </span><span class="n">value</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n"><a href="../../reference/string/basic_string.html">std::string</a></span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"{"</span><span class="p">;</span>
<span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">is_first</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">true</span><span class="p">;</span>
<span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">:</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span><span class="n"><a href="../../reference/meta/nonstatic_data_members_of.html">std::meta::nonstatic_data_members_of</a></span><span class="p">(</span><span class="o">^^</span><span class="n">T</span><span class="p">,</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/access_context/unchecked.html">std::meta::access_context::unchecked</a></span><span class="p">())))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">skips</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/annotations_of_with_type.html">std::meta::annotations_of_with_type</a></span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="o">^^</span><span class="n">Skip</span><span class="p">));</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="p">(</span><span class="n">skips</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">renames</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n"><a href="../../reference/meta/define_static_array.html">std::define_static_array</a></span><span class="p">(</span>
<span class="w"> </span><span class="n"><a href="../../reference/meta/annotations_of_with_type.html">std::meta::annotations_of_with_type</a></span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="o">^^</span><span class="n">Rename</span><span class="p">));</span>
<span class="w"> </span><span class="c1">// Renameアノテーションがあればその名前を、なければメンバ変数名をキーにする</span>
<span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n"><a href="../../reference/string_view/basic_string_view.html">std::string_view</a></span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="p">(</span><span class="n">renames</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="w"> </span><span class="o">></span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n"><a href="../../reference/string_view/basic_string_view.html">std::string_view</a></span><span class="p">{[</span><span class="o">:</span><span class="n"><a href="../../reference/meta/constant_of.html">std::meta::constant_of</a></span><span class="p">(</span><span class="n">renames</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="o">:</span><span class="p">].</span><span class="n">name</span><span class="p">};</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n"><a href="../../reference/meta/identifier_of.html">std::meta::identifier_of</a></span><span class="p">(</span><span class="n">m</span><span class="p">);</span>

