9 Declarations [dcl]

9.13 Attributes [dcl.attr]

9.13.12 Annotations [dcl.attr.annotation]

An annotation may be applied to a base-specifier or to a declaration D of a type, type alias, variable, function, function parameter of non-void type, namespace, enumerator, or non-static data member, unless
  • the host scope of X differs from its target scope or
  • X is a non-defining friend declaration,
where X is
  • if D is a function parameter declaration in a function declarator ([dcl.fct]) of a function declaration and
  • D otherwise.
[Note 1: 
An annotation on a parameter-declaration in a function definition applies to both the function parameter and the variable.
[Example 1: 
void f([[=1]] int x); void f([[=2]] int y) constexpr auto rp = parameters_of(@^^f@)[0]; constexpr auto ry = variable_of(rp); static_assert(ry == ^^y); static_assert(annotations_of(rp).size() == 2); // both [1, 2] static_assert(annotations_of(ry).size() == 1); // just [2] static_assert(annotations_of(rp)[1] == annotations_of(ry)[0]);
— end example]
— end note]
Let E be the expression std​::​meta​::​reflect_constant(constant-expression).
E shall be a constant expression; the result of E is the underlying constant of the annotation.
Each annotation or instantiation thereof produces a unique annotation.
[Example 2: 
[[=1]] void f(); [[=2, =3, =2]] void g(); void g [[=4, =2]] (); f has one annotation and g has five annotations.
These can be queried with metafunctions such as std​::​​meta​::​​annotations_of ([meta.reflection.annotation]).
— end example]
[Example 3: template<int> int x [[=1]]; static_assert(annotations_of(^^x<0>) != annotations_of(^^x<1>)); // OK — end example]
Substituting into an annotation is not in the immediate context.
[Example 4: template<class T> [[=T::type()]] void f(T t); void f(int); void g() { f(0); // OK f('0'); // error, substituting into the annotation results in an invalid expression } — end example]