Updates to 'access_context' and 'define_static_*'.

Accessors for the former; put the latter in 'std::*'.
This commit is contained in:
Dan Katz
2025-04-10 12:29:41 -04:00
parent 2f5c771fe7
commit 0504407a85
5 changed files with 106 additions and 77 deletions

View File

@@ -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 <typename ValTy, ValTy... Vals>
inline constexpr ValTy FixedArray[sizeof...(Vals)] = {Vals...};
template <auto &S>
inline constexpr span StaticSpan(S, size(S));
template <typename ValTy>
consteval span<const ValTy> impl(const span<const ValTy> &in) {
if (in.size() == 0)
return {};
vector Args = {^^ValTy};
for (const auto &V : in)
Args.push_back(reflect_value(V));
return extract<span<const ValTy>>(
substitute(^^StaticSpan, { substitute(^^FixedArray, Args) }));
}
} // namespace __define_static
template <ranges::input_range R>
requires (is_constructible_v<ranges::range_value_t<R>,
ranges::range_reference_t<R>>)
consteval auto define_static_array(R &&elems)
-> span<const ranges::range_value_t<R>> {
using ValTy = ranges::range_value_t<R>;
using ImplTy = span<const ValTy>(*)(const span<const ValTy> &);
auto impl = extract<ImplTy>(substitute(^^__define_static::impl, {^^ValTy}));
vector<ValTy> 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<span<const char>> 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<span<const char8_t>> 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 <typename ValTy, ValTy... Vals>
inline constexpr ValTy FixedArray[sizeof...(Vals)] = {Vals...};
template <auto &S>
inline constexpr span StaticSpan(S, size(S));
template <typename ValTy>
consteval span<const ValTy> impl(const span<const ValTy> &in) {
if (in.size() == 0)
return {};
vector Args = {^^ValTy};
for (const auto &V : in)
Args.push_back(meta::reflect_value(V));
return meta::extract<span<const ValTy>>(
meta::substitute(^^StaticSpan, { meta::substitute(^^FixedArray, Args) }));
}
} // namespace __define_static
template <ranges::input_range R>
requires (is_constructible_v<ranges::range_value_t<R>,
ranges::range_reference_t<R>>)
consteval auto define_static_array(R &&elems)
-> span<const ranges::range_value_t<R>> {
using ValTy = ranges::range_value_t<R>;
using ImplTy = span<const ValTy>(*)(const span<const ValTy> &);
auto impl = meta::extract<ImplTy>(meta::substitute(^^__define_static::impl,
{^^ValTy}));
vector<ValTy> 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<span<const char>> 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<span<const char8_t>> 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

View File

@@ -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<std::vector>())[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<std::vector>())[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

View File

@@ -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);
}();

View File

@@ -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);

View File

@@ -24,10 +24,10 @@
// =============
namespace static_arrays {
constexpr auto empty = std::meta::define_static_array(std::vector<int>{});
constexpr auto empty = std::define_static_array(std::vector<int>{});
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<Cls>{1, 3, 5});
constexpr auto objs = std::define_static_array(std::vector<Cls>{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 <auto S> consteval auto fn() { return S[0]; }
static_assert(fn<std::meta::define_static_string("literal")>() == 'l');
static_assert(fn<std::define_static_string("literal")>() == 'l');
} // namespace static_strings