Produces a language construct from a reflection value, effectively “splicing” the reflection into source code.
Syntax
[:constant-expression:](1) typename [:constant-expression:](2) template [:constant-expression:](3) 1) A splice specifier whose meaning depends on the context.
2) A splice specifier that is a type specifier.
3) A splice specifier that designates a template. If it does not appear as an expression, the specifier must be followed by a template argument list (enclosed in <>), and must be the left operand of the scope resolution operator ::, e.g., template[:R:]<int>::is_always_lock_free.
Explanation
In general, a splice specifier has the same meaning as the name or value of the language construct represented by constant-expression. It is said to designate that language construct.
Expression
For a splice specifier to be an expression, the specifier must not follow the typename keyword, nor be followed by the scope resolution operator ::.
structS{staticconstexprinta=1;};template<typename>structTCls{staticconstexprintb=2;};constexprintc=[:^^S:]::a;// [:^^S:] is not an expressionconstexprintd=template[:^^TCls:]<int>::b;// template [:^^TCls:]<int> is not an expressiontemplate<autoV>constexprinte=[:V:];// [:V:] is an expressionconstexprintf=template[:^^e:]<^^S::a>;// template [:^^e:]<^^S::a> is an expressionconstexprautog=typename[:^^int:](42);// typename [:^^int:] is a type specifierAn unparenthesized splice expression cannot appear as a template argument.
A splice expression can designates a function, an object, a data member, a variable, a structured binding, a value, or an enumerator. But it cannot designate a constructor, a destructor, an unnamed bit-field, or a local entity such that naming it would cause it to be captured by a lambda expression.
A splice expression that designates a variable or structured binding V is valid only if V has static or thread
or is declared in a scope enclosing the expression.
A splice expression that designates a
or
implicit object member function
can only be used:
as the second operand of
class member access expression
;
as the operand of
to form a
;
in an
if it designates a non-static data member.
Unlike names of non-static members, a splice expression [:r:] is never implicitly transformed to this->[:r:].
A splice expression [:r:] may describe a direct base class relationship(D, B) (e.g., if r is an element of std::meta::bases_of(^^D,ctx)). A direct base class relationship can only appear as the second operand of class member access expression. This class member access expression converts the first operand to “reference to (possibly
-qualified) D” and results in the B direct base class subobject of the converted value. This can be used to access a base class subject that would otherwise be ambiguous or inaccessible.
A splice expression can designate a function template or variable template only if the template keyword is used.
Type
A splice specifier that is a type specifier must not be followed by the scope resolution operator ::, and must either be preceded by typename, or be in a
.
template<std::meta::infoR>voidtfn(){typename[:R:]::typem;// OK, typename applies to the qualified name// (Here [:R:] is a scope, not a type specifier.)}structS{usingtype=int;};voidfn(){[:^^S::type:]*var;// error: [:^^S::type:] is an expressiontypename[:^^S::type:]*var;// OK, declares variable with type int*}usingalias=[:^^S::type:];// OK, type-only contextA splice type specifier can designate a type, a class template, or an alias template. If it designates a template and does not have a template argument list, it is subject to
class template argument deduction
.
A splice specifier may also appear in a
.
template<typenameT>conceptC=requires{typename[:T::r1:];// fails if T::r1 is not a reflection of a typetypename[:T::r2:]<int>;// fails if T::r2 is not a reflection of some template Z// for which Z<int> is a type};Scope
For a splice specifier that is the left operand of the the scope resolution operator ::, if the specifier has a template argument list, it must be preceded by typename or template.
template<intV>structTCls{staticconstexprints=V;usingtype=int;};intv1=[:^^TCls<1>:]::s;intv2=template[:^^TCls:]<2>::s;// OK, 'template' is part of the splice specifiertypename[:^^TCls:]<3>::typev3=3;// OK, 'typename' is part of the typename-specifiertemplate[:^^TCls:]<3>::typev4=4;// OK, 'template' is part of the splice specifiertypenametemplate[:^^TCls:]<3>::typev5=5;// OK, same as v3[:^^TCls:]<3>::typev6=6;// error: unexpected <The splice specifier must designate a class or enumeration type, or a namespace. The splice specifier in [:r:]<TArgs...>:: or template[:r:]<TArgs...>:: must designate a class template or alias template.
Namespace
A splice specifier [:r:] in a
definition or a
must designate a namespace name or namespace alias that is not the global namespace. A
r can appear in a namespace alias definition (but not in a using directive), which causes the namespace alias to be dependent as well.
Notes
In addition to splice specifiers, the function templates
and
can also turn a reflection to the value it represents. Unlike splice specifiers, they do not require the arguments to be constant expressions in isolation, but have different restrictions.
Feature-test macro ValueStdFeature
(C++26)
Example
See also