diff --git a/libcxx/include/experimental/meta b/libcxx/include/experimental/meta index e45eff4ca943..00c52a7f345a 100644 --- a/libcxx/include/experimental/meta +++ b/libcxx/include/experimental/meta @@ -361,6 +361,11 @@ consteval auto annotate(info) -> info; // modeling access control (P3547) struct access_context { + access_context() = delete; + + consteval auto scope() const -> info; + consteval auto naming_class() const -> info; + static consteval auto current() noexcept -> access_context; static consteval auto unprivileged() noexcept -> access_context; static consteval auto unchecked() noexcept -> access_context; @@ -942,22 +947,26 @@ consteval auto is_class_type(info r) -> bool { class access_context { consteval access_context(info scope, info naming_class) noexcept - : scope{scope}, naming_class{naming_class} { } + : d_scope{scope}, d_naming_class{naming_class} { } public: - const info scope; - const info naming_class; + const info d_scope; + const info d_naming_class; + + consteval access_context() = delete; - consteval access_context() noexcept : scope{^^::}, naming_class{} { }; consteval access_context(const access_context &) noexcept = default; consteval access_context(access_context &&) noexcept = default; + consteval info scope() const { return d_scope; } + consteval info naming_class() const { return d_naming_class; } + static consteval access_context current() noexcept { return {__metafunction(detail::__metafn_access_context), {}}; } static consteval access_context unprivileged() noexcept { - return access_context{}; + return access_context{^^::, info{}}; } static consteval access_context unchecked() noexcept { @@ -968,7 +977,7 @@ public: if (!is_class_type(new_naming_class)) throw "naming class must be a reflection of a class type"; - return access_context{scope, new_naming_class}; + return access_context{d_scope, new_naming_class}; } }; @@ -977,7 +986,7 @@ consteval auto is_accessible(info r, access_context ctx) -> bool { return true; return __metafunction(detail::__metafn_is_accessible, - r, ctx.scope, ctx.naming_class); + r, ctx.scope(), ctx.naming_class()); } #endif // __has_feature(access_contexts) @@ -1572,55 +1581,6 @@ consteval auto bit_size_of(info r) -> size_t { return __metafunction(detail::__metafn_bit_size_of, r); } -namespace __define_static { - -template -inline constexpr ValTy FixedArray[sizeof...(Vals)] = {Vals...}; - -template -inline constexpr span StaticSpan(S, size(S)); - -template -consteval span impl(const span &in) { - if (in.size() == 0) - return {}; - - vector Args = {^^ValTy}; - for (const auto &V : in) - Args.push_back(reflect_value(V)); - - return extract>( - substitute(^^StaticSpan, { substitute(^^FixedArray, Args) })); -} -} // namespace __define_static - -template - requires (is_constructible_v, - ranges::range_reference_t>) -consteval auto define_static_array(R &&elems) - -> span> { - using ValTy = ranges::range_value_t; - using ImplTy = span(*)(const span &); - auto impl = extract(substitute(^^__define_static::impl, {^^ValTy})); - - vector vals(from_range, elems); - return impl(vals); -} - -// Returns a static string having the provided contents. -consteval auto define_static_string(string_view in) -> const char * { - const char nullterm[1] = {0}; - vector> v = {in, nullterm}; - return define_static_array(views::join(v)).data(); -} - -consteval auto define_static_string(u8string_view in) -> const char8_t * { - const char8_t nullterm[1] = {0}; - vector> v = {in, nullterm}; - return define_static_array(views::join(v)).data(); -} - - // Type trait wrappers consteval auto is_void_type(info r) -> bool { @@ -2383,6 +2343,62 @@ consteval auto has_complete_definition(info r) -> bool { #endif // __has_feature(access_contexts) +_LIBCPP_END_NAMESPACE_REFLECTION_V2 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __define_static { + +template +inline constexpr ValTy FixedArray[sizeof...(Vals)] = {Vals...}; + +template +inline constexpr span StaticSpan(S, size(S)); + +template +consteval span impl(const span &in) { + if (in.size() == 0) + return {}; + + vector Args = {^^ValTy}; + for (const auto &V : in) + Args.push_back(meta::reflect_value(V)); + + return meta::extract>( + meta::substitute(^^StaticSpan, { meta::substitute(^^FixedArray, Args) })); +} +} // namespace __define_static + +template + requires (is_constructible_v, + ranges::range_reference_t>) +consteval auto define_static_array(R &&elems) + -> span> { + using ValTy = ranges::range_value_t; + using ImplTy = span(*)(const span &); + auto impl = meta::extract(meta::substitute(^^__define_static::impl, + {^^ValTy})); + + vector vals(from_range, elems); + return impl(vals); +} + +// Returns a static string having the provided contents. +consteval auto define_static_string(string_view in) -> const char * { + const char nullterm[1] = {0}; + vector> v = {in, nullterm}; + return define_static_array(views::join(v)).data(); +} + +consteval auto define_static_string(u8string_view in) -> const char8_t * { + const char8_t nullterm[1] = {0}; + vector> v = {in, nullterm}; + return define_static_array(views::join(v)).data(); +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_BEGIN_NAMESPACE_REFLECTION_V2 // ==================================== // (u8)display_string_of implementation diff --git a/libcxx/test/std/experimental/reflection/layout.pass.cpp b/libcxx/test/std/experimental/reflection/layout.pass.cpp index b4f9f5f78464..c9981221fc7c 100644 --- a/libcxx/test/std/experimental/reflection/layout.pass.cpp +++ b/libcxx/test/std/experimental/reflection/layout.pass.cpp @@ -50,20 +50,29 @@ struct BitField { }; static_assert(offset_of(^^BitField::bf1) == std::meta::member_offset{0, 0}); static_assert(offset_of(^^BitField::bf2) == std::meta::member_offset{0, 1}); -static_assert(offset_of(nonstatic_data_members_of(^^BitField, {})[2]) == - std::meta::member_offset{1, 0}); +static_assert( + offset_of( + nonstatic_data_members_of(^^BitField, + std::meta::access_context::current())[2]) == + std::meta::member_offset{1, 0}); static_assert(offset_of(^^BitField::bf3) == std::meta::member_offset{1, 0}); static_assert(offset_of(^^BitField::bf4) == std::meta::member_offset{1, 3}); static_assert(bit_size_of(^^BitField::bf1) == 1); static_assert(bit_size_of(^^BitField::bf2) == 2); -static_assert(bit_size_of((members_of(^^BitField, {}) | - std::views::filter(std::meta::is_bit_field) | - std::ranges::to())[2]) == 0); +static_assert( + bit_size_of( + (members_of(^^BitField, std::meta::access_context::current()) | + std::views::filter(std::meta::is_bit_field) | + std::ranges::to())[2]) == + 0); static_assert(bit_size_of(^^BitField::bf3) == 3); static_assert(bit_size_of(^^BitField::bf4) == 3); // unnamed bitfield not included. -static_assert(nonstatic_data_members_of(^^BitField, {}).size() == 4); +static_assert( + nonstatic_data_members_of( + ^^BitField, + std::meta::access_context::current()).size() == 4); static_assert(size_of(^^BitField) == 4); alignas(64) int i1; @@ -125,12 +134,18 @@ struct A { char a; }; struct B { bool b; }; struct C : A, B {}; -static_assert(offset_of(bases_of(^^C, {})[0]) == std::meta::member_offset{0, 0}); -static_assert(offset_of(bases_of(^^C, {})[1]) == std::meta::member_offset{1, 0}); +static_assert( + offset_of(bases_of(^^C, std::meta::access_context::current())[0]) == + std::meta::member_offset{0, 0}); +static_assert( + offset_of(bases_of(^^C, std::meta::access_context::current())[1]) == + std::meta::member_offset{1, 0}); struct V { }; struct D : V { virtual void fn() = 0; }; -static_assert(offset_of(bases_of(^^D, {})[0]) == std::meta::member_offset{0, 0}); +static_assert( + offset_of(bases_of(^^D, std::meta::access_context::current())[0]) == + std::meta::member_offset{0, 0}); } // namespace base_offsets diff --git a/libcxx/test/std/experimental/reflection/member-visibility.pass.cpp b/libcxx/test/std/experimental/reflection/member-visibility.pass.cpp index b16d2940fb05..ab288a3ca1da 100644 --- a/libcxx/test/std/experimental/reflection/member-visibility.pass.cpp +++ b/libcxx/test/std/experimental/reflection/member-visibility.pass.cpp @@ -248,16 +248,14 @@ consteval access_context FriendFnOfAccess() { // ===================== -static_assert(access_context{}.scope == ^^::); -static_assert(access_context::current().scope == ^^::); +static_assert(access_context::current().scope() == ^^::); namespace new_accessibility_api { -static_assert(access_context::current().scope == ^^::new_accessibility_api); +static_assert(access_context::current().scope() == ^^::new_accessibility_api); void fn() { - static_assert(access_context{}.scope == ^^::); - static_assert(access_context::current().scope == ^^fn); + static_assert(access_context::current().scope() == ^^fn); [] { - constexpr auto repr = access_context::current().scope; + constexpr auto repr = access_context::current().scope(); static_assert(is_function(repr)); static_assert(repr != ^^fn); }(); diff --git a/libcxx/test/std/experimental/reflection/p2996-ex-parsing-command-line-options-2.sh.cpp b/libcxx/test/std/experimental/reflection/p2996-ex-parsing-command-line-options-2.sh.cpp index da04ed31b90a..3d1e77f10c80 100644 --- a/libcxx/test/std/experimental/reflection/p2996-ex-parsing-command-line-options-2.sh.cpp +++ b/libcxx/test/std/experimental/reflection/p2996-ex-parsing-command-line-options-2.sh.cpp @@ -76,7 +76,7 @@ struct Clap { }; template for (constexpr auto Pair : - std::meta::define_static_array([]() consteval { + std::define_static_array([]() consteval { auto ctx = std::meta::access_context::current(); auto spec_members = nonstatic_data_members_of(^^Spec, ctx); diff --git a/libcxx/test/std/experimental/reflection/static-arrays.pass.cpp b/libcxx/test/std/experimental/reflection/static-arrays.pass.cpp index 9287ca45e75c..2f2b95b9c08b 100644 --- a/libcxx/test/std/experimental/reflection/static-arrays.pass.cpp +++ b/libcxx/test/std/experimental/reflection/static-arrays.pass.cpp @@ -24,10 +24,10 @@ // ============= namespace static_arrays { -constexpr auto empty = std::meta::define_static_array(std::vector{}); +constexpr auto empty = std::define_static_array(std::vector{}); static_assert(empty.size() == 0); -constexpr auto ints = std::meta::define_static_array(std::vector{1, 3, 5}); +constexpr auto ints = std::define_static_array(std::vector{1, 3, 5}); static_assert(ints.size() == 3); static_assert(ints[0] == 1 && ints[1] == 3 && ints[2] == 5); @@ -37,11 +37,11 @@ struct Cls { consteval Cls(int v) : k(v) {} consteval Cls(const Cls &rhs) : k(rhs.k + 1) {} }; -constexpr auto objs = std::meta::define_static_array(std::vector{1, 3, 5}); +constexpr auto objs = std::define_static_array(std::vector{1, 3, 5}); static_assert(objs.size() == 3); static_assert(objs[0].k == 5 && objs[1].k == 7 && objs[2].k == 9); -constexpr auto infos = std::meta::define_static_array( +constexpr auto infos = std::define_static_array( nonstatic_data_members_of(^^Cls)); static_assert(infos.size() == 1); static_assert(infos[0] == ^^Cls::k); @@ -54,7 +54,7 @@ static_assert(infos[0] == ^^Cls::k); namespace static_strings { // Ensure 'define_static_string("literal")' can be used as a template argument. template consteval auto fn() { return S[0]; } -static_assert(fn() == 'l'); +static_assert(fn() == 'l'); } // namespace static_strings