From Jason Turner

[meta.reflection.queries]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpx9fkwf_u/{from.md → to.md} +688 -0
tmp/tmpx9fkwf_u/{from.md → to.md} RENAMED
@@ -0,0 +1,688 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Reflection queries <a id="meta.reflection.queries">[[meta.reflection.queries]]</a>
2
+
3
+ ``` cpp
4
+ consteval bool has-type(info r); // exposition only
5
+ ```
6
+
7
+ *Returns:* `true` if `r` represents a value, annotation, object,
8
+ variable, function whose type does not contain an undeduced placeholder
9
+ type and that is not a constructor or destructor, enumerator, non-static
10
+ data member, unnamed bit-field, direct base class relationship, data
11
+ member description, or function parameter. Otherwise, `false`.
12
+
13
+ ``` cpp
14
+ consteval info type_of(info r);
15
+ ```
16
+
17
+ *Returns:*
18
+
19
+ - If `r` represents the iᵗʰ parameter of a function F, then the iᵗʰ type
20
+ in the parameter-type-list of F[[dcl.fct]].
21
+ - Otherwise, if `r` represents a value, object, variable, function,
22
+ non-static data member, or unnamed bit-field, then the type of what is
23
+ represented by `r`.
24
+ - Otherwise, if `r` represents an annotation, then
25
+ `type_of(constant_of(r))`.
26
+ - Otherwise, if `r` represents an enumerator N of an enumeration E,
27
+ then:
28
+ - If E is defined by a declaration D that precedes a point P in the
29
+ evaluation context and P does not occur within an *enum-specifier*
30
+ of D, then a reflection of E.
31
+ - Otherwise, a reflection of the type of N prior to the closing brace
32
+ of the *enum-specifier* as specified in  [[dcl.enum]].
33
+ - Otherwise, if `r` represents a direct base class relationship (D, B),
34
+ then a reflection of B.
35
+ - Otherwise, for a data member description
36
+ (T, N, A, W, *NUA*)[[class.mem.general]], a reflection of the type T.
37
+
38
+ *Throws:* `meta::exception` unless *`has-type`*`(r)` is `true`.
39
+
40
+ ``` cpp
41
+ consteval info object_of(info r);
42
+ ```
43
+
44
+ *Returns:*
45
+
46
+ - If `r` represents an object, then `r`.
47
+ - Otherwise, if `r` represents a reference, then a reflection of the
48
+ object referred to by that reference.
49
+ - Otherwise, `r` represents a variable; a reflection of the object
50
+ declared by that variable.
51
+
52
+ *Throws:* `meta::exception` unless `r` is a reflection representing
53
+ either
54
+
55
+ - an object with static storage duration [[basic.stc.general]], or
56
+ - a variable that either declares or refers to such an object, and if
57
+ that variable is a reference R, then either
58
+ - R is usable in constant expressions [[expr.const]], or
59
+ - the lifetime of R began within the core constant expression
60
+ currently under evaluation.
61
+
62
+ [*Example 1*:
63
+
64
+ ``` cpp
65
+ int x;
66
+ int& y = x;
67
+
68
+ static_assert(^^x != ^^y); // OK, r and y are different variables so their
69
+ // reflections compare different
70
+ static_assert(object_of(^^x) == object_of(^^y)); // OK, because y is a reference
71
+ // to x, their underlying objects are the same
72
+ ```
73
+
74
+ — *end example*]
75
+
76
+ ``` cpp
77
+ consteval info constant_of(info r);
78
+ ```
79
+
80
+ Let R be a constant expression of type `info` such that R` == r` is
81
+ `true`. If `r` represents an annotation, then let C be its underlying
82
+ constant.
83
+
84
+ *Effects:* Equivalent to:
85
+
86
+ ``` cpp
87
+ if constexpr (is_annotation(R)) {
88
+ return C;
89
+ } else {
90
+ return reflect_constant([: R :]);
91
+ }
92
+ ```
93
+
94
+ *Throws:* `meta::exception` unless either `r` represents an annotation
95
+ or `[: `R` :]` is a valid *splice-expression*[[expr.prim.splice]].
96
+
97
+ [*Example 2*:
98
+
99
+ ``` cpp
100
+ constexpr int x = 0;
101
+ constexpr int y = 0;
102
+
103
+ static_assert(^^x != ^^y); // OK, x and y are different variables,
104
+ // so their reflections compare different
105
+ static_assert(constant_of(^^x) ==
106
+ constant_of(^^y)); // OK, both constant_of(\reflexpr{x)} and
107
+ // constant_of(\reflexpr{y)} represent the value 0
108
+ static_assert(constant_of(^^x) ==
109
+ reflect_constant(0)); // OK, likewise
110
+
111
+ struct S { int m; };
112
+ constexpr S s {42};
113
+ static_assert(is_object(constant_of(^^s)) &&
114
+ is_object(reflect_object(s)));
115
+ static_assert(constant_of(^^s) != // OK, template parameter object that is template-argument-
116
+ reflect_object(s)); // equivalent to s is a different object than s
117
+ static_assert(constant_of(^^s) ==
118
+ constant_of(reflect_object(s))); // OK
119
+
120
+ consteval info fn() {
121
+ constexpr int x = 42;
122
+ return ^^x;
123
+ }
124
+ constexpr info r = constant_of(fn()); // error: x is outside its lifetime
125
+ ```
126
+
127
+ — *end example*]
128
+
129
+ ``` cpp
130
+ consteval bool is_public(info r);
131
+ consteval bool is_protected(info r);
132
+ consteval bool is_private(info r);
133
+ ```
134
+
135
+ *Returns:* `true` if `r` represents either
136
+
137
+ - a class member or unnamed bit-field that is public, protected, or
138
+ private, respectively, or
139
+ - a direct base class relationship (D, B) for which B is, respectively,
140
+ a public, protected, or private base class of D.
141
+
142
+ Otherwise, `false`.
143
+
144
+ ``` cpp
145
+ consteval bool is_virtual(info r);
146
+ ```
147
+
148
+ *Returns:* `true` if `r` represents either a virtual member function or
149
+ a direct base class relationship (D, B) for which B is a virtual base
150
+ class of D. Otherwise, `false`.
151
+
152
+ ``` cpp
153
+ consteval bool is_pure_virtual(info r);
154
+ consteval bool is_override(info r);
155
+ ```
156
+
157
+ *Returns:* `true` if `r` represents a member function that is pure
158
+ virtual or overrides another member function, respectively. Otherwise,
159
+ `false`.
160
+
161
+ ``` cpp
162
+ consteval bool is_final(info r);
163
+ ```
164
+
165
+ *Returns:* `true` if `r` represents a final class or a final member
166
+ function. Otherwise, `false`.
167
+
168
+ ``` cpp
169
+ consteval bool is_deleted(info r);
170
+ consteval bool is_defaulted(info r);
171
+ ```
172
+
173
+ *Returns:* `true` if `r` represents a function that is a deleted
174
+ function [[dcl.fct.def.delete]] or defaulted
175
+ function [[dcl.fct.def.default]], respectively. Otherwise, `false`.
176
+
177
+ ``` cpp
178
+ consteval bool is_user_provided(info r);
179
+ consteval bool is_user_declared(info r);
180
+ ```
181
+
182
+ *Returns:* `true` if `r` represents a function that is user-provided or
183
+ user-declared [[dcl.fct.def.default]], respectively. Otherwise, `false`.
184
+
185
+ ``` cpp
186
+ consteval bool is_explicit(info r);
187
+ ```
188
+
189
+ *Returns:* `true` if `r` represents a member function that is declared
190
+ explicit. Otherwise, `false`.
191
+
192
+ [*Note 1*: If `r` represents a member function template that is
193
+ declared explicit, `is_explicit(r)` is still `false` because in general,
194
+ such queries for templates cannot be answered. — *end note*]
195
+
196
+ ``` cpp
197
+ consteval bool is_noexcept(info r);
198
+ ```
199
+
200
+ *Returns:* `true` if `r` represents a `noexcept` function type or a
201
+ function with a non-throwing exception specification [[except.spec]].
202
+ Otherwise, `false`.
203
+
204
+ [*Note 2*: If `r` represents a function template that is declared
205
+ `noexcept`, `is_noexcept(r)` is still `false` because in general, such
206
+ queries for templates cannot be answered. — *end note*]
207
+
208
+ ``` cpp
209
+ consteval bool is_bit_field(info r);
210
+ ```
211
+
212
+ *Returns:* `true` if `r` represents a bit-field, or if `r` represents a
213
+ data member description (T, N, A, W, *NUA*)[[class.mem.general]] for
214
+ which W is not $\bot$. Otherwise, `false`.
215
+
216
+ ``` cpp
217
+ consteval bool is_enumerator(info r);
218
+ consteval bool is_annotation(info r);
219
+ ```
220
+
221
+ *Returns:* `true` if `r` represents an enumerator or annotation,
222
+ respectively. Otherwise, `false`.
223
+
224
+ ``` cpp
225
+ consteval bool is_const(info r);
226
+ consteval bool is_volatile(info r);
227
+ ```
228
+
229
+ Let T be `type_of(r)` if *`has-type`*`(r)` is `true`. Otherwise, let T
230
+ be `dealias(r)`.
231
+
232
+ *Returns:* `true` if `T` represents a const or volatile type,
233
+ respectively, or a const- or volatile-qualified function type,
234
+ respectively. Otherwise, `false`.
235
+
236
+ ``` cpp
237
+ consteval bool is_mutable_member(info r);
238
+ ```
239
+
240
+ *Returns:* `true` if `r` represents a `mutable` non-static data member.
241
+ Otherwise, `false`.
242
+
243
+ ``` cpp
244
+ consteval bool is_lvalue_reference_qualified(info r);
245
+ consteval bool is_rvalue_reference_qualified(info r);
246
+ ```
247
+
248
+ Let T be `type_of(r)` if *`has-type`*`(r)` is `true`. Otherwise, let T
249
+ be `dealias(r)`.
250
+
251
+ *Returns:* `true` if T represents an lvalue- or rvalue-qualified
252
+ function type, respectively. Otherwise, `false`.
253
+
254
+ ``` cpp
255
+ consteval bool has_static_storage_duration(info r);
256
+ consteval bool has_thread_storage_duration(info r);
257
+ consteval bool has_automatic_storage_duration(info r);
258
+ ```
259
+
260
+ *Returns:* `true` if `r` represents an object or variable that has
261
+ static, thread, or automatic storage duration,
262
+ respectively [[basic.stc]]. Otherwise, `false`.
263
+
264
+ [*Note 3*: It is not possible to have a reflection representing an
265
+ object or variable having dynamic storage duration. — *end note*]
266
+
267
+ ``` cpp
268
+ consteval bool has_internal_linkage(info r);
269
+ consteval bool has_module_linkage(info r);
270
+ consteval bool has_external_linkage(info r);
271
+ consteval bool has_c_language_linkage(info r);
272
+ consteval bool has_linkage(info r);
273
+ ```
274
+
275
+ *Returns:* `true` if `r` represents a variable, function, type,
276
+ template, or namespace whose name has internal linkage, module linkage,
277
+ C language linkage, or any linkage, respectively [[basic.link]].
278
+ Otherwise, `false`.
279
+
280
+ ``` cpp
281
+ consteval bool is_complete_type(info r);
282
+ ```
283
+
284
+ *Returns:* `true` if `is_type(r)` is `true` and there is some point in
285
+ the evaluation context from which the type represented by `dealias(r)`
286
+ is not an incomplete type [[basic.types]]. Otherwise, `false`.
287
+
288
+ ``` cpp
289
+ consteval bool is_enumerable_type(info r);
290
+ ```
291
+
292
+ A type T is *enumerable* from a point P if either
293
+
294
+ - T is a class type complete at point P or
295
+ - T is an enumeration type defined by a declaration D such that D is
296
+ reachable from P but P does not occur within an *enum-specifier* of
297
+ D[[dcl.enum]].
298
+
299
+ *Returns:* `true` if `dealias(r)` represents a type that is enumerable
300
+ from some point in the evaluation context. Otherwise, `false`.
301
+
302
+ [*Example 3*:
303
+
304
+ ``` cpp
305
+ class S;
306
+ enum class E;
307
+ static_assert(!is_enumerable_type(^^S));
308
+ static_assert(!is_enumerable_type(^^E));
309
+
310
+ class S {
311
+ void mfn() {
312
+ static_assert(is_enumerable_type(^^S));
313
+ }
314
+ static_assert(!is_enumerable_type(^^S));
315
+ };
316
+ static_assert(is_enumerable_type(^^S));
317
+
318
+ enum class E {
319
+ A = is_enumerable_type(^^E) ? 1 : 2
320
+ };
321
+ static_assert(is_enumerable_type(^^E));
322
+ static_assert(static_cast<int>(E::A) == 2);
323
+ ```
324
+
325
+ — *end example*]
326
+
327
+ ``` cpp
328
+ consteval bool is_variable(info r);
329
+ ```
330
+
331
+ *Returns:* `true` if `r` represents a variable. Otherwise, `false`.
332
+
333
+ ``` cpp
334
+ consteval bool is_type(info r);
335
+ consteval bool is_namespace(info r);
336
+ ```
337
+
338
+ *Returns:* `true` if `r` represents an entity whose underlying entity is
339
+ a type or namespace, respectively. Otherwise, `false`.
340
+
341
+ ``` cpp
342
+ consteval bool is_type_alias(info r);
343
+ consteval bool is_namespace_alias(info r);
344
+ ```
345
+
346
+ *Returns:* `true` if `r` represents a type alias or namespace alias,
347
+ respectively. Otherwise, `false`.
348
+
349
+ [*Note 4*: A specialization of an alias template is a type
350
+ alias. — *end note*]
351
+
352
+ ``` cpp
353
+ consteval bool is_function(info r);
354
+ ```
355
+
356
+ *Returns:* `true` if `r` represents a function. Otherwise, `false`.
357
+
358
+ ``` cpp
359
+ consteval bool is_conversion_function(info r);
360
+ consteval bool is_operator_function(info r);
361
+ consteval bool is_literal_operator(info r);
362
+ ```
363
+
364
+ *Returns:* `true` if `r` represents a function that is a conversion
365
+ function [[class.conv.fct]], operator function [[over.oper]], or literal
366
+ operator [[over.literal]], respectively. Otherwise, `false`.
367
+
368
+ ``` cpp
369
+ consteval bool is_special_member_function(info r);
370
+ consteval bool is_constructor(info r);
371
+ consteval bool is_default_constructor(info r);
372
+ consteval bool is_copy_constructor(info r);
373
+ consteval bool is_move_constructor(info r);
374
+ consteval bool is_assignment(info r);
375
+ consteval bool is_copy_assignment(info r);
376
+ consteval bool is_move_assignment(info r);
377
+ consteval bool is_destructor(info r);
378
+ ```
379
+
380
+ *Returns:* `true` if `r` represents a function that is a special member
381
+ function [[special]], a constructor, a default constructor, a copy
382
+ constructor, a move constructor, an assignment operator, a copy
383
+ assignment operator, a move assignment operator, or a destructor,
384
+ respectively. Otherwise, `false`.
385
+
386
+ ``` cpp
387
+ consteval bool is_function_parameter(info r);
388
+ ```
389
+
390
+ *Returns:* `true` if `r` represents a function parameter. Otherwise,
391
+ `false`.
392
+
393
+ ``` cpp
394
+ consteval bool is_explicit_object_parameter(info r);
395
+ ```
396
+
397
+ *Returns:* `true` if `r` represents a function parameter that is an
398
+ explicit object parameter [[dcl.fct]]. Otherwise, `false`.
399
+
400
+ ``` cpp
401
+ consteval bool has_default_argument(info r);
402
+ ```
403
+
404
+ *Returns:* If `r` represents a parameter P of a function F, then:
405
+
406
+ - If F is a specialization of a templated function T, then `true` if
407
+ there exists a declaration D of T that precedes some point in the
408
+ evaluation context and D specifies a default argument for the
409
+ parameter of T corresponding to P. Otherwise, `false`.
410
+ - Otherwise, if there exists a declaration D of F that precedes some
411
+ point in the evaluation context and D specifies a default argument for
412
+ P, then `true`.
413
+
414
+ Otherwise, `false`.
415
+
416
+ ``` cpp
417
+ consteval bool has_ellipsis_parameter(info r);
418
+ ```
419
+
420
+ *Returns:* `true` if `r` represents a function or function type that has
421
+ an ellipsis in its parameter-type-list [[dcl.fct]]. Otherwise, `false`.
422
+
423
+ ``` cpp
424
+ consteval bool is_template(info r);
425
+ ```
426
+
427
+ *Returns:* `true` if `r` represents a function template, class template,
428
+ variable template, alias template, or concept. Otherwise, `false`.
429
+
430
+ [*Note 5*: A template specialization is not a template. For example,
431
+ `is_template(``)` is `true` but `is_template(``)` is
432
+ `false`. — *end note*]
433
+
434
+ ``` cpp
435
+ consteval bool is_function_template(info r);
436
+ consteval bool is_variable_template(info r);
437
+ consteval bool is_class_template(info r);
438
+ consteval bool is_alias_template(info r);
439
+ consteval bool is_conversion_function_template(info r);
440
+ consteval bool is_operator_function_template(info r);
441
+ consteval bool is_literal_operator_template(info r);
442
+ consteval bool is_constructor_template(info r);
443
+ consteval bool is_concept(info r);
444
+ ```
445
+
446
+ *Returns:* `true` if `r` represents a function template, variable
447
+ template, class template, alias template, conversion function template,
448
+ operator function template, literal operator template, constructor
449
+ template, or concept, respectively. Otherwise, `false`.
450
+
451
+ ``` cpp
452
+ consteval bool is_value(info r);
453
+ consteval bool is_object(info r);
454
+ ```
455
+
456
+ *Returns:* `true` if `r` represents a value or object, respectively.
457
+ Otherwise, `false`.
458
+
459
+ ``` cpp
460
+ consteval bool is_structured_binding(info r);
461
+ ```
462
+
463
+ *Returns:* `true` if `r` represents a structured binding. Otherwise,
464
+ `false`.
465
+
466
+ ``` cpp
467
+ consteval bool is_class_member(info r);
468
+ consteval bool is_namespace_member(info r);
469
+ consteval bool is_nonstatic_data_member(info r);
470
+ consteval bool is_static_member(info r);
471
+ consteval bool is_base(info r);
472
+ ```
473
+
474
+ *Returns:* `true` if `r` represents a class member, namespace member,
475
+ non-static data member, static member, or direct base class
476
+ relationship, respectively. Otherwise, `false`.
477
+
478
+ ``` cpp
479
+ consteval bool has_default_member_initializer(info r);
480
+ ```
481
+
482
+ *Returns:* `true` if `r` represents a non-static data member that has a
483
+ default member initializer. Otherwise, `false`.
484
+
485
+ ``` cpp
486
+ consteval bool has_parent(info r);
487
+ ```
488
+
489
+ *Returns:*
490
+
491
+ - If `r` represents the global namespace, then `false`.
492
+ - Otherwise, if `r` represents an entity that has C language
493
+ linkage [[dcl.link]], then `false`.
494
+ - Otherwise, if `r` represents an entity that has a language linkage
495
+ other than C++ language linkage, then an *implementation-defined*
496
+ value.
497
+ - Otherwise, if `r` represents a type that is neither a class nor
498
+ enumeration type, then `false`.
499
+ - Otherwise, if `r` represents an entity or direct base class
500
+ relationship, then `true`.
501
+ - Otherwise, `false`.
502
+
503
+ ``` cpp
504
+ consteval info parent_of(info r);
505
+ ```
506
+
507
+ *Returns:*
508
+
509
+ - If `r` represents a non-static data member that is a direct member of
510
+ an anonymous union, or an unnamed bit-field declared within the
511
+ *member-specification* of such a union, then a reflection representing
512
+ the innermost enclosing anonymous union.
513
+ - Otherwise, if `r` represents an enumerator, then a reflection
514
+ representing the corresponding enumeration type.
515
+ - Otherwise, if `r` represents a direct base class relationship (D, B),
516
+ then a reflection representing D.
517
+ - Otherwise, let E be a class, function, or namespace whose class scope,
518
+ function parameter scope, or namespace scope, respectively, is the
519
+ innermost such scope that either is, or encloses, the target scope of
520
+ a declaration of what is represented by `r`.
521
+ - If E is the function call operator of a closure type for a
522
+ *consteval-block-declaration*[[dcl.pre]], then
523
+ `parent_of(parent_of(``))`. \[*Note 1*: In this case, the first
524
+ `parent_of` will be the closure type, so the second `parent_of` is
525
+ necessary to give the parent of that closure type. — *end note*]
526
+ - Otherwise, .
527
+
528
+ *Throws:* `meta::exception` unless `has_parent(r)` is `true`.
529
+
530
+ [*Example 4*:
531
+
532
+ ``` cpp
533
+ struct I { };
534
+
535
+ struct F : I {
536
+ union {
537
+ int o;
538
+ };
539
+
540
+ enum N {
541
+ A
542
+ };
543
+ };
544
+
545
+ constexpr auto ctx = std::meta::access_context::current();
546
+
547
+ static_assert(parent_of(^^F) == ^^::);
548
+ static_assert(parent_of(bases_of(^^F, ctx)[0]) == ^^F);
549
+ static_assert(is_union_type(parent_of(^^F::o)));
550
+ static_assert(parent_of(^^F::N) == ^^F);
551
+ static_assert(parent_of(^^F::A) == ^^F::N);
552
+ ```
553
+
554
+ — *end example*]
555
+
556
+ ``` cpp
557
+ consteval info dealias(info r);
558
+ ```
559
+
560
+ *Returns:* A reflection representing the underlying entity of what `r`
561
+ represents.
562
+
563
+ *Throws:* `meta::exception` unless `r` represents an entity.
564
+
565
+ [*Example 5*:
566
+
567
+ ``` cpp
568
+ using X = int;
569
+ using Y = X;
570
+ static_assert(dealias(^^int) == ^^int);
571
+ static_assert(dealias(^^X) == ^^int);
572
+ static_assert(dealias(^^Y) == ^^int);
573
+ ```
574
+
575
+ — *end example*]
576
+
577
+ ``` cpp
578
+ consteval bool has_template_arguments(info r);
579
+ ```
580
+
581
+ *Returns:* `true` if `r` represents a specialization of a function
582
+ template, variable template, class template, or an alias template.
583
+ Otherwise, `false`.
584
+
585
+ ``` cpp
586
+ consteval info template_of(info r);
587
+ ```
588
+
589
+ *Returns:* A reflection of the template of the specialization
590
+ represented by `r`.
591
+
592
+ *Throws:* `meta::exception` unless `has_template_arguments(r)` is
593
+ `true`.
594
+
595
+ ``` cpp
596
+ consteval vector<info> template_arguments_of(info r);
597
+ ```
598
+
599
+ *Returns:* A `vector` containing reflections of the template arguments
600
+ of the template specialization represented by `r`, in the order in which
601
+ they appear in the corresponding template argument list. For a given
602
+ template argument A, its corresponding reflection R is determined as
603
+ follows:
604
+
605
+ - If A denotes a type or type alias, then R is a reflection representing
606
+ the underlying entity of A. \[*Note 2*: R always represents a type,
607
+ never a type alias. — *end note*]
608
+ - Otherwise, if A denotes a class template, variable template, concept,
609
+ or alias template, then R is a reflection representing A.
610
+ - Otherwise, A is a constant template argument [[temp.arg.nontype]]. Let
611
+ P be the corresponding template parameter.
612
+ - If P has reference type, then R is a reflection representing the
613
+ object or function referred to by A.
614
+ - Otherwise, if P has class type, then R represents the corresponding
615
+ template parameter object.
616
+ - Otherwise, R is a reflection representing the value of A.
617
+
618
+ *Throws:* `meta::exception` unless `has_template_arguments(r)` is
619
+ `true`.
620
+
621
+ [*Example 6*:
622
+
623
+ ``` cpp
624
+ template<class T, class U = T> struct Pair { };
625
+ template<class T> struct Pair<char, T> { };
626
+ template<class T> using PairPtr = Pair<T*>;
627
+
628
+ static_assert(template_of(^^Pair<int>) == ^^Pair);
629
+ static_assert(template_of(^^Pair<char, char>) == ^^Pair);
630
+ static_assert(template_arguments_of(^^Pair<int>).size() == 2);
631
+ static_assert(template_arguments_of(^^Pair<int>)[0] == ^^int);
632
+
633
+ static_assert(template_of(^^PairPtr<int>) == ^^PairPtr);
634
+ static_assert(template_arguments_of(^^PairPtr<int>).size() == 1);
635
+
636
+ struct S { };
637
+ int i;
638
+ template<int, int&, S, template<class> class>
639
+ struct X { };
640
+ constexpr auto T = ^^X<1, i, S{}, PairPtr>;
641
+ static_assert(is_value(template_arguments_of(T)[0]));
642
+ static_assert(is_object(template_arguments_of(T)[1]));
643
+ static_assert(is_object(template_arguments_of(T)[2]));
644
+ static_assert(template_arguments_of(T)[3] == ^^PairPtr);
645
+ ```
646
+
647
+ — *end example*]
648
+
649
+ ``` cpp
650
+ consteval vector<info> parameters_of(info r);
651
+ ```
652
+
653
+ *Returns:*
654
+
655
+ - If `r` represents a function F, then a `vector` containing reflections
656
+ of the parameters of F, in the order in which they appear in a
657
+ declaration of F.
658
+ - Otherwise, `r` represents a function type T; a `vector` containing
659
+ reflections of the types in parameter-type-list [[dcl.fct]] of T, in
660
+ the order in which they appear in the parameter-type-list.
661
+
662
+ *Throws:* `meta::exception` unless `r` represents a function or a
663
+ function type.
664
+
665
+ ``` cpp
666
+ consteval info variable_of(info r);
667
+ ```
668
+
669
+ *Returns:* The reflection of the parameter variable corresponding to
670
+ `r`.
671
+
672
+ *Throws:* `meta::exception` unless
673
+
674
+ - `r` represents a parameter of a function F and
675
+ - there is a point P in the evaluation context for which the innermost
676
+ non-block scope enclosing P is the function parameter
677
+ scope [[basic.scope.param]] associated with F.
678
+
679
+ ``` cpp
680
+ consteval info return_type_of(info r);
681
+ ```
682
+
683
+ *Returns:* The reflection of the return type of the function or function
684
+ type represented by `r`.
685
+
686
+ *Throws:* `meta::exception` unless either `r` represents a function and
687
+ *`has-type`*`(r)` is `true` or `r` represents a function type.
688
+