次æC++2c(C++26)æ¨æºè¦æ ¼ã«åãã¦æ¤è¨ãé²ãã§ãã ãªãã¬ã¯ã·ã§ã³(reflection) ã«ã¤ãã¦ã¡ã¢ãæ¬è¨äºã®å 容ã¯ææ¡ææ¸ P2996R10 ã«åºã¥ãã
è¦ç´ï¼
- æ°ããæ¼ç®åï¼
^^
ã[:
ã¨:]
ã®çµ - æ°ããæ§æ
- ãªãã¬ã¯ãå¼ï¼
^^èå¥å
ã^^åå
- ã¹ãã©ã¤ãµæ§æï¼
[:r:]
- constevalãããã¯å®£è¨ï¼
consteval { statement(s) }
- ãªãã¬ã¯ãå¼ï¼
- æ°ããæ¨æºããã<meta>
std::meta::info
å- åå空é
std::meta
以ä¸ã®ãªãã¬ã¯ã·ã§ã³ã»ã¡ã¿é¢æ°ç¾¤
- C++ã¨ã³ãã£ãã£ãæã¤ããããéçæ
å ±ã®ååãããµãã¼ã
- ä¾1ï¼åæåã®ååãåå¾ï¼âid:yohhoy:20250228ï¼ãã¨ã³ãã£ãã£ã®ã½ã¼ã¹ã³ã¼ãä½ç½®
source_location
ãåå¾ã - ä¾2ï¼ã¯ã©ã¹åã®å ¨ã¡ã³ãæ å ±ãåå¾ããã³ãã¬ã¼ãå¼æ°æ å ±ãåå¾ãã¨ã¤ãªã¢ã¹å æ å ±ãåå¾ã
- ä¾1ï¼åæåã®ååãåå¾ï¼âid:yohhoy:20250228ï¼ãã¨ã³ãã£ãã£ã®ã½ã¼ã¹ã³ã¼ãä½ç½®
- ãã³ãã¬ã¼ããã©ã¡ã¼ã¿ã®ç½®æ(substitute)æä½ããµãã¼ã
- SFINAE(Substitution Failure Is Not An Error)ã¨ãã¥ã¬ã¼ã·ã§ã³åä½ãè¡ãããã¨æãã
- ãªãã¬ã¯ã·ã§ã³æ
å ±ããã®éæä½(aggregate)å®ç¾©ããµãã¼ã
- ã¯ã©ã¹ãå
±ç¨ä½(
union
)ã®åæ å ±ãã³ã³ãã¤ã«æã«çµã¿ç«ã¦ãã¡ã¿ã»ããã°ã©ãã³ã°ã
- ã¯ã©ã¹ãå
±ç¨ä½(
- ãã³ãã¬ã¼ãã»ã¡ã¿é¢æ°(<type_traits>)ã«å¯¾å¿ãããªãã¬ã¯ã·ã§ã³ã»ã¡ã¿é¢æ°(<meta>)
- ä¾1ï¼
is_pointer_v<T>
âbool meta::is_pointer_type(info)
- ä¾2ï¼
remove_cvref_t<T>
âinfo meta::remove_cvref(info)
- ä¾1ï¼
ãªãã¬ã¯ã·ã§ã³æ¼ç®å
C++ã¨ã³ãã£ãã£ã«å¯¾ãã¦ãªãã¬ã¯ã·ã§ã³æ¼ç®å(reflection operator)^^
ãé©ç¨ãããªãã¬ã¯ãå¼(reflect-expression)ã¯ãstd::meta::info
åã®ãªãã¬ã¯ã·ã§ã³å¤(reflection value; reflection)ã«è©ä¾¡ãããããªãã¬ã¯ã·ã§ã³æ¼ç®å^^
ãªãã©ã³ãã«ã¯ä¸è¨C++ã¨ã³ãã£ãã£ãæå®ã§ããã
- åå空éã¨ã¤ãªã¢ã¹(namespace alias)
- åå空é(namespace)
^^::
== ã°ãã¼ãã«åå空éã®ãªãã¬ã¯ã·ã§ã³å¤
- ã³ã³ã»ãã(concept)
- ã¯ã©ã¹ãã³ãã¬ã¼ã(class template)
- é¢æ°ãã³ãã¬ã¼ã(function template)
- å¤æ°ãã³ãã¬ã¼ã(primary variable template)
- ã¨ã¤ãªã¢ã¹ãã³ãã¬ã¼ã(alias template)
- å(type)
- åã¨ã¤ãªã¢ã¹(type alias)
- é¢æ°(function)
- å¤æ°(variable)
- æ§é åæç¸(structured binding)
- åæå(enumerator)
- éstaticãã¼ã¿ã¡ã³ã(non-static data member)
次ã®C++ã¨ã³ãã£ãã£ã«ã¯é©ç¨ã§ããªãã
- éåãã³ãã¬ã¼ããã©ã¡ã¼ã¿(non-type template parameter) *1
- ããã¯ã»ã¤ã³ãã¯ã¹å¼(pack-index-expression) *2
ãã¼ãï¼å±æ§(attribute)ã«å¯¾ãããªãã¬ã¯ã·ã§ã³ã¯P3385ã«ã¦æ¤è¨ä¸*3ãå±æ§ã¨æ§æãä¼¼ãã¦ã¼ã¶å®ç¾©ã¢ããã¼ã·ã§ã³(annotation)å°å
¥ã¨ãªãã¬ã¯ã·ã§ã³ã¯P3394ã«ã¦æ¤è¨ä¸*4ã
ãªãã¬ã¯ã·ã§ã³å¤
ãã¬ã¯ã·ã§ã³å¤ã表ç¾ããstd::meta::info
åã®ç¹å¾´ï¼
- ããã©ã«ãæ§ç¯ã¯ãã«ã»ãªãã¬ã¯ã·ã§ã³(null reflection)å¤ã¨ãªãã
- ãªãã¬ã¯ã·ã§ã³å¤ã®çå¤æ¯è¼(
=
,!=
)ããµãã¼ãããã - åä¸ã®ä¸éæ(opaque)åã¨ãã¦è¨è¨ãããã
- <type_traits>ãããï¼ãªãã¬ã¯ã·ã§ã³å¤ã®ååã(query)ãè¡ããªãã¬ã¯ã·ã§ã³ã»ã¡ã¿é¢æ°ç¾¤ãæä¾ã
- æ°ãããã©ã¤ããªåã«ãã´ãªï¼âid:yohhoy:20141122ï¼ã¨ãã¦è¿½å ãããã
- <type_traits>ãããï¼
std::is_reflection
é¢æ°ã追å ã
- <type_traits>ãããï¼
- ãªãã¬ã¯ã·ã§ã³æ¼ç®åã§ã¯ç´æ¥åå¾ã§ããªãç¹æ®ãªãªãã¬ã¯ã·ã§ã³å¤ãåå¨ããã
- ç¡åããããã£ã¼ã«ã(unnamed bit-field)ï¼ç¡åããããã£ã¼ã«ããå«ãã¯ã©ã¹å
T
ããmembers_of(^^T)[n]
- ãã¼ã¿ã¡ã³ãè¨è¿°(data member description)ï¼
data_member_spec(^^T, {.name="m1"})
- ç´æ¥åºåºã¯ã©ã¹é¢ä¿(direct base class relationship)ï¼public/protected/privateç¶æ¿é¢ä¿ãæ´¾çã¯ã©ã¹å
D
ããbases_of(^^D)[0]
- ãã¼ãï¼é¢æ°ãã©ã¡ã¼ã¿(function parameter)ã¯(PDF)P3096ã«ã¦æ¤è¨ä¸ã*5
- ç¡åããããã£ã¼ã«ã(unnamed bit-field)ï¼ç¡åããããã£ã¼ã«ããå«ãã¯ã©ã¹å
#include <meta> // çµæåã¯å ¨ã¦ std::meta::info constexpr auto r1 = ^^int; // å constexpr auto r2 = ^^std::string; // åã¨ã¤ãªã¢ã¹ constexpr auto r3 = ^^std::malloc; // é¢æ° constexpr auto r4 = ^^std::vector; // ã¯ã©ã¹ãã³ãã¬ã¼ã constexpr auto r5 = ^^std::same_as; // ã³ã³ã»ãã constexpr auto r6 = ^^std::linalg; // åå空é // ãªãã¬ã¯ã·ã§ã³ã»ã¡ã¿é¢æ°ã¯åå空é std::meta ã«å±ãã // å¼æ°å std::meta::info ããã®ADLã«ããã¹ã³ã¼ãæå®ã¯çç¥å¯è½ static_assert( is_type(r1) ); static_assert( is_type(r2) && is_type_alias(r2) ); static_assert( is_function(r3) ); static_assert( is_template(r4) && is_class_template(r4) ); static_assert( is_template(r5) && is_concept(r5) ); static_assert( is_namespace(r6) );
ã¹ãã©ã¤ãµæ§æ
std::meta::info
åã®ãªãã¬ã¯ã·ã§ã³å¤r
ããC++ã¨ã³ãã£ãã£ãå¾ããã¹ãã©ã¤ã¹æå®å(splice-specifier)[:r:]
ãæ°ããæ§æè¦ç´ ã¨ãã¦è¿½å ãããã
- ã¹ãã©ã¤ã¹å¼(splice-expression)ï¼
[:r:]
ãtemplate [:r:]
ã§å®æ°å¤ãå¾ããr
ããã³ãã¬ã¼ãã表ãã¨ãtemplate
ãã¼ã¯ã¼ããå¿ è¦ãr
ãã³ã³ã»ããã表ãã¨ãã¯ã¹ãã©ã¤ã¹ä¸å¯ã*6
- ã¹ãã©ã¤ã¹ã»åæå®å(splice-type-specifier)ï¼
[:r:]
ãtypename [:r:]
ã§åãæå®ã- åãèªæã«è¦æ±ãããã³ã³ããã¹ãã§ã¯
typename
ãã¼ã¯ã¼ãçç¥å¯è½ã
- åãèªæã«è¦æ±ãããã³ã³ããã¹ãã§ã¯
- ã¹ãã©ã¤ã¹ã»ã¹ã³ã¼ãæå®å(splice-scope-specifier)ï¼
[:r:]::
ã§åå空éãæå®ã
constexpr auto r_type = ^^int; typename [:r_type:] x; // int x; [:r_type:] y; // int y; namespace NS { void fn(); } constexpr auto r_ns = ^^NS; [:r_ns:]::fn(); // NS::fn(); template<int N> void fn(); constexpr int C = 42; constexpr auto r_tfn = ^^fn; constexpr auto r_var = ^^C; template [:r_tfn:]<[:r_var:]>(); // f<42>();
éæä½ã»å ±ç¨ä½ã®å®ç¾©
std::meta::define_aggregate
é¢æ°ã¨constevalãããã¯å®£è¨(consteval-block-declaration)ãçµã¿åããã¦ãã¯ã©ã¹åãå
±ç¨ä½åã«å¯¾ãã¦ãªãã¬ã¯ã·ã§ã³å¤ãããã¼ã¿ã¡ã³ããå®ç¾©ã§ãããstd::meta::data_member_spec
é¢æ°ï¼std::meta::data_member_options
å*7ã«ãããã¼ã¿ã¡ã³ãè¨è¿°ã»ãªãã¬ã¯ã·ã§ã³å¤ãçæããå®ç¾©å¯¾è±¡åã¨ãã¼ã¿ã¡ã³ãè¨è¿°ãªã¹ããæå®ããã
#include <meta> struct Point; consteval { std::meta::define_aggregate(^^Point, { data_member_spec(^^float, {.name = "x"}), data_member_spec(^^float, {.name = "y"}) }); } // struct Point { float x; float y; };ã¨ç価
// P2996R10, §4.8 A Simple Tuple Type #include <meta> template<typename... Ts> struct Tuple { struct storage; consteval { // storageã¯ã©ã¹ã«(ç¡å)ãã¼ã¿ã¡ã³ãã追å ãã define_aggregate(^^storage, {data_member_spec(^^Ts)...}); } storage data; Tuple(const Ts& ...vs): data{vs...} {} }; // Tuple<int, char>ããä¸è¨ã¯ã©ã¹(ç¸å½)ãå®ç¾© struct Tuple<int, char>::storage { int _u0; char _u1; }; // _uN ã¯ç¡åãã¼ã¿ã¡ã³ãã®ããã¡ã³ãåã§ã®ã¢ã¯ã»ã¹ä¸å¯ // nonstatic_data_members_ofé¢æ°ã¨ã¹ãã©ã¤ã¹å¼ãå©ç¨ã // data.[:nonstatic_data_members_of(^^storage)[N]:] ã¨ãã
é¢é£URL
- P2996R10 Reflection for C++26
- P3289R1 consteval blocksï¼P2996R10ã¸çµ±åæ¸ã¿ï¼
- P3547R1 Modeling Access Control With Reflectionï¼P2996R10ã¸çµ±åæ¸ã¿ï¼
- (PDF) P3096R6 Function Parameter Reflection in Reflection for C++26
- P3385R3 Attributes reflection
- P3394R1 Annotations for Reflection
- https://github.com/bloomberg/clang-p2996
*1:éåãã³ãã¬ã¼ããã©ã¡ã¼ã¿ V ã«å¯¾ã㦠std::meta::reflect_value(V) ã¨ããã°ãªãã¬ã¯ã·ã§ã³å¤ãå¾ãããã
*2:C++2cè¨èªä»æ§ã¸ã®æ¡æã決å®ãã¦ãã args...[n] å¼ã(PDF)P2662R3 åç §ã
*3:https://github.com/cplusplus/papers/issues/2042
*4:https://github.com/cplusplus/papers/issues/2074
*5:https://github.com/cplusplus/papers/issues/1764
*6:ãªãã¬ã¯ã·ã§ã³ã»ã¡ã¿é¢æ° std::meta::can_substitute ãç¨ãã¦ãããã³ã³ã»ãããç¨ããå¶ç´ãæºãããã(satisfied)ãå¦ããå¤å®å¯è½ãä¾ï¼can_substitute(^^std::integral, {^^int});
*7:ãã¼ã¿ã¡ã³ãã® name, alignment, bit_width, no_unique_address ãå¶å¾¡å¯è½ã