21 Metaprogramming library [meta]

21.4 Reflection [meta.reflection]

21.4.7 Access control context [meta.reflection.access.context]

The access_context class is a non-aggregate type that represents a namespacee, class, or function from which queries pertaining to access rules may be performed, as well as the designating class ([class.access.base]), if any.
An access_context has an associated scope and designating class.
namespace std::meta { struct access_context { access_context() = delete; consteval info scope() const; consteval info designating_class() const; static consteval access_context current() noexcept; static consteval access_context unprivileged() noexcept; static consteval access_context unchecked() noexcept; consteval access_context via(info cls) const; }; }
access_context is a structural type.
Two values ac1 and ac2 of type access_context are template-argument-equivalent ([temp.type]) if a1.scope() and a2.scope() are template-argument-equivalent and ac1.designating_class() and ac2.designating_class() are template-argument-equivalent.
consteval info scope() const; consteval info designating_class() const;
Returns: The access_context's associated scope and designating class, respectively.
static consteval access_context current() noexcept;
Given a program point P, let eval-point(P) be the following program point:
  • If a potentially-evaluated subexpression ([intro.execution]) of a default member initializer I for a member of class C ([class.mem.general]) appears at P, then a point determined as follows:
    • If an aggregate initialization is using I, eval-point(Q), where Q is the point at which that aggregate initialization appears.
    • Otherwise, if an initialization by an inherited constructor ([class.inhctor.init]) is using I, a point whose immediate scope is the class scope corresponding to C.
    • Otherwise, a point whose immediate scope is the function parameter scope corresponding to the constructor definition that is using I.
  • Otherwise, if a potentially-evaluated subexpression of a default argument ([dcl.fct.default]) appears at P, eval-point(Q), where Q is the point at which the invocation of the function ([expr.call]) using that default argument appears.
  • Otherwise, if the immediate scope of P is a function parameter scope introduced by a declaration D, and P appears either before the locus of D or within the trailing requires-clause of D, a point whose immediate scope is the innermost scope enclosing the locus of D that is not a template parameter scope.
  • Otherwise, if the immediate scope of P is a function parameter scope introduced by a lambda-expression L whose lambda-introducer appears at point Q, and P appears either within the trailing-return-type or the trailing requires-clause of L, eval-point(Q).
  • Otherwise, if the innermost non-block scope enclosing P is the function parameter scope introduced by a consteval-block-declaration ([dcl.pre]), a point whose immediate scope is that inhabited by the outermost consteval-block-declaration D containing P such that each scope (if any) that intervenes between P and the function parameter scope introduced by D is either
  • Otherwise, P.
Given a scope S, let ctx-scope(S) be the following scope:
  • If S is a class scope or namespace scope, S.
  • Otherwise, if S is a function parameter scope introduced by the declaration of a function, S.
  • Otherwise, if S is a lambda scope introduced by a lambda-expression L, the function parameter scope corresponding to the call operator of the closure type of L.
  • Otherwise, ctx-scope(), where is the parent scope of S.
Returns: An access_context whose designating class is the null reflection and whose scope represents the function, class, or namespace whose corresponding function parameter scope, class scope, or namespace scope, respectively, is ctx-scope(S), where S is the immediate scope of eval-point(P) and P is the point at which the invocation of current lexically appears.
[Example 1: struct A { int a = 0; consteval A(int p) : a(p) {} }; struct B : A { using A::A; consteval B(int p, int q) : A(p * q) {} info s = access_context::current().scope(); }; struct C : B { using B::B; }; struct Agg { consteval bool eq(info rhs = access_context::current().scope()) { return s == rhs; } info s = access_context::current().scope(); }; namespace NS { static_assert(Agg{}.s == access_context::current().scope()); // OK static_assert(Agg{}.eq()); // OK static_assert(B(1).s == ^^B); // OK static_assert(is_constructor(B{1, 2}.s) && parent_of(B{1, 2}.s) == ^^B); // OK static_assert(is_constructor(C{1, 2}.s) && parent_of(C{1, 2}.s) == ^^B); // OK auto fn() -> [:is_namespace(access_context::current().scope()) ? ^^int : ^^bool:]; static_assert(type_of(^^fn) == ^^auto()->int); // OK template<auto R> struct TCls { consteval bool fn() requires (is_type(access_context::current().scope())) { return true; // OK, scope is TCls<R>. } }; static_assert(TCls<0>{}.fn()); // OK } — end example]
Remarks: current is not an addressable function ([namespace.std]).
An invocation of current that appears at a program point P is value-dependent ([temp.dep.constexpr]) if eval-point(P) is enclosed by a scope corresponding to a templated entity.
static consteval access_context unprivileged() noexcept;
Returns: An access_context whose designating class is the null reflection and whose scope is the global namespace.
static consteval access_context unchecked() noexcept;
Returns: An access_context whose designating class and scope are both the null reflection.
static consteval access_context via(info cls) noexcept;
Constant When: cls is either the null reflection or a reflection of a complete class type.
Returns: An access_context whose scope is this->scope() and whose designating class is cls.