-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathreflection.html
More file actions
753 lines (664 loc) · 85.4 KB
/
Copy pathreflection.html
File metadata and controls
753 lines (664 loc) · 85.4 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
<!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 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)」機能を導入する。" />
<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=b2142794d8ca9924d883222f0df04f8c964ce722">
<link rel="icon" type="image/png" sizes="32x32" href="../../static/favicons/favicon-32x32.png?cachebust=b2142794d8ca9924d883222f0df04f8c964ce722">
<link rel="icon" type="image/png" sizes="16x16" href="../../static/favicons/favicon-16x16.png?cachebust=b2142794d8ca9924d883222f0df04f8c964ce722">
<link rel="manifest" href="../../manifest.json?cachebust=b2142794d8ca9924d883222f0df04f8c964ce722">
<meta name="theme-color" content="#f5f8fc">
<link rel="stylesheet" href="../../static/pygments/default.css?cachebust=b2142794d8ca9924d883222f0df04f8c964ce722">
<!-- <link rel="stylesheet" href="../../static/css/root.css"> -->
<link href="../../static/kunai/css/kunai-stage-0.css?cachebust=b2142794d8ca9924d883222f0df04f8c964ce722" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-1.css?cachebust=b2142794d8ca9924d883222f0df04f8c964ce722" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-2.css?cachebust=b2142794d8ca9924d883222f0df04f8c964ce722" rel="stylesheet">
<link href="../../static/kunai/css/kunai-stage-3.css?cachebust=b2142794d8ca9924d883222f0df04f8c964ce722" rel="stylesheet">
<script type="text/javascript" src="../../static/kunai/js/kunai-vendor.js?cachebust=b2142794d8ca9924d883222f0df04f8c964ce722"></script>
<script type="text/javascript" src="../../static/kunai/js/kunai.js?cachebust=b2142794d8ca9924d883222f0df04f8c964ce722"></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": "99250cd4295e1e24ac630b5d6a0256d6d939e2c0", "source": "#include <meta>\n#include <print>\n#include <string_view>\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": "9bef0d1d173b9dbefd6082856b1426c96b2d8162", "source": "#include <meta>\n#include <functional>\n#include <string>\n#include <print>\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"}], "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>
最終更新日時(UTC):
<span itemprop="datePublished" content="2026-05-14T07:51:06">
2026年05月14日 07時51分06秒
</span>
<br/>
<span itemprop="author" itemscope itemtype="http://schema.org/Person">
<span itemprop="name">Akira Takahashi</span>
</span>
が更新
</small></p>
<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型であり、実行時には存在できない</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="99250cd4295e1e24ac630b5d6a0256d6d939e2c0"><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="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="9bef0d1d173b9dbefd6082856b1426c96b2d8162"><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="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>
<h2><a href="#relative-page" id="relative-page">関連項目</a></h2>
<ul>
<li><a href="../../reference/meta.html"><code><meta></code>ヘッダ</a></li>
<li><a href="expansion_statements.html">C++26 コンパイル時のタプルやリストを展開処理する<code>template for</code>文</a></li>
<li><a href="allowing_exception_throwing_in_constant-evaluation.html">C++26 定数評価での例外送出を許可</a></li>
</ul>
<h2>参照</h2>
<ul>
<li><a href="https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2996r13.html" target="_blank">P2996R13 Reflection for C++26</a><ul>
<li>C++26での静的リフレクションの基本機能。リフレクション演算子<code>^^</code>、スプライス演算子<code>[: :]</code>、<code>std::meta::info</code>型、<code><meta></code>ヘッダのメタ関数群を導入する。</li>
</ul>
</li>
<li><a href="https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3394r4.html" target="_blank">P3394R4 Annotations for Reflection</a><ul>
<li>宣言にコンパイル時定数を付加するアノテーション機能<code>[[=expr]]</code>と、それを取得するための<code>annotations_of()</code>メタ関数を追加する。</li>
</ul>
</li>
<li><a href="https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3293r3.html" target="_blank">P3293R3 Splicing a base class subobject</a><ul>
<li>基底クラスのリフレクションに対するメンバアクセスのスプライス<code>obj.[:base:]</code>と、基底クラスとメンバ変数を統合取得する<code>subobjects_of()</code>を追加する。</li>
</ul>
</li>
<li><a href="https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3096r12.pdf" target="_blank">P3096R12 Function Parameter Reflection in Reflection for C++26</a><ul>
<li>関数パラメータのリフレクションを追加する。<code>parameters_of()</code>、<code>return_type_of()</code>、<code>has_default_argument()</code>などのメタ関数を導入する。</li>
</ul>
</li>
<li><a href="https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3491r3.html" target="_blank">P3491R3 <code>define_static_{string,object,array}</code></a><ul>
<li>コンパイル時に計算した値を静的ストレージに配置するための<code>define_static_string()</code>、<code>define_static_array()</code>、<code>define_static_object()</code>を追加する。</li>
</ul>
</li>
<li><a href="https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3560r2.html" target="_blank">P3560R2 Error Handling in Reflection</a><ul>
<li>リフレクションのメタ関数のエラー処理として<code>std::meta::exception</code><a class="cpprefjp-defined-word" data-desc="問題が発生したときに、現在実行位置を過去に通過・記録した位置に戻し、文脈情報を添えて紐づけられた処理(例外ハンドラー)を呼び出す仕組み。またはその事態">例外</a>クラスを導入する。コンパイル時<a class="cpprefjp-defined-word" data-desc="問題が発生したときに、現在実行位置を過去に通過・記録した位置に戻し、文脈情報を添えて紐づけられた処理(例外ハンドラー)を呼び出す仕組み。またはその事態">例外</a>として動作する。</li>
</ul>
</li>
<li><a href="https://open-std.org/jtc1/sc22/wg21/docs/papers/2026/p3598r0.pdf" target="_blank">P3598R0 CWG 3158 — <code>const</code>-ification of Splice Expressions</a><ul>
<li>変数のリフレクションに対するスプライス式に対して、対応する<em>id-expression</em>と同様の文脈依存な型調整(<code>const</code>化など)を適用するよう仕様を修正する。</li>
</ul>
</li>
</ul></div>
</div>
</div>
</div>
<div id="sidebar" class="col-sm-3 col-sm-pull-9">
</div>
</div>
</div>
</main>
<footer class="footer navbar navbar-default">
<div class="container-fluid">
<p><small>
本サイトの情報は、
<a href="https://creativecommons.org/licenses/by/4.0/deed.ja" rel="nofollow">クリエイティブ・コモンズ 表示 4.0 非移植 ライセンス(CC BY)</a>
の下に提供されています。
</small></p>
</div>
</footer>
</body>
</html>