Adding reflect_constant_array (#140)
* Attempting to add reflect_constant_array * Fixing extract from array * Fixing test * Adding bounded test case
This commit is contained in:
@@ -3098,13 +3098,17 @@ bool extract(APValue &Result, ASTContext &C, MetaActions &Meta,
|
||||
Range.getBegin(), ResultTy, VK_LValue,
|
||||
Decl, nullptr);
|
||||
} else if (auto *ArrTy = dyn_cast<ArrayType>(Decl->getType())) {
|
||||
QualType PtrTy = C.getPointerType(ArrTy->getElementType());
|
||||
QualType Elt = ArrTy->getElementType();
|
||||
if (auto *VD = dyn_cast<VarDecl>(Decl)) {
|
||||
if (VD->isConstexpr()) {
|
||||
Elt.addConst();
|
||||
}
|
||||
}
|
||||
|
||||
ReturnsLValue = true;
|
||||
if (RawResultTy.getCanonicalType().getTypePtr() !=
|
||||
PtrTy.getCanonicalType().getTypePtr())
|
||||
if (!RawResultTy->isPointerType() || !RawResultTy->getPointeeType().isAtLeastAsQualifiedAs(Elt, C))
|
||||
return Diagnoser(Range.getBegin(), diag::metafn_extract_type_mismatch)
|
||||
<< 1 << PtrTy << 1 << ResultTy << Range;
|
||||
<< 1 << C.getPointerType(Elt) << 1 << ResultTy << Range;
|
||||
|
||||
NestedNameSpecifierLocBuilder NNSLocBuilder;
|
||||
if (auto *ParentClsDecl = dyn_cast_or_null<CXXRecordDecl>(
|
||||
|
||||
@@ -1010,7 +1010,7 @@ public:
|
||||
|
||||
consteval auto is_accessible(info r, access_context ctx) -> bool {
|
||||
// Note: The accessibility of an enumerator may be looked up in a class
|
||||
// for which it's not a member, since that enumerator could be
|
||||
// for which it's not a member, since that enumerator could be
|
||||
if (!is_class_member(r) && !is_base(r) && !is_enumerator(r))
|
||||
return true;
|
||||
|
||||
@@ -1402,8 +1402,8 @@ consteval auto is_user_declared(info r) -> bool {
|
||||
}
|
||||
|
||||
// Returns a reflection of the value held by the provided argument.
|
||||
template <typename T>
|
||||
requires (!is_reference_v<T> &&
|
||||
template <typename T>
|
||||
requires (!is_reference_v<T> &&
|
||||
__metafunction(detail::__metafn_is_structural_type, ^^T))
|
||||
consteval auto reflect_constant(const T &r) -> info {
|
||||
return __metafunction(detail::__metafn_reflect_result, ^^T,
|
||||
@@ -2320,44 +2320,36 @@ consteval auto has_complete_definition(info r) -> bool {
|
||||
return __metafunction(detail::__metafn_has_complete_definition, r);
|
||||
}
|
||||
|
||||
_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_constant(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 reflect_constant_array(R &&elems) -> info {
|
||||
using ValTy = ranges::range_value_t<R>;
|
||||
vector Args = {^^ValTy};
|
||||
for (const auto &V : elems)
|
||||
Args.push_back(reflect_constant(V));
|
||||
return substitute(^^__define_static::FixedArray, Args);
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_REFLECTION_V2
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
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);
|
||||
meta::info array = meta::reflect_constant_array(elems);
|
||||
return span<const ValTy>(extract<const ValTy*>(array), meta::extent(type_of(array)));
|
||||
}
|
||||
|
||||
// Returns a static string having the provided contents.
|
||||
|
||||
@@ -41,7 +41,7 @@ struct Cls {
|
||||
};
|
||||
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);
|
||||
static_assert(objs[0].k == 4 && objs[1].k == 6 && objs[2].k == 8);
|
||||
|
||||
constexpr auto infos = std::define_static_array(
|
||||
nonstatic_data_members_of(^^Cls,
|
||||
|
||||
@@ -211,8 +211,11 @@ namespace extract_ref_semantics {
|
||||
// ====================
|
||||
|
||||
namespace extract_array_as_ptr {
|
||||
constexpr int arr[] = {1, 2, 3};
|
||||
static_assert(extract<const int *>(^^arr)[2] == 3);
|
||||
constexpr int a[] = {1, 2, 3};
|
||||
static_assert(extract<const int *>(^^a)[2] == 3);
|
||||
|
||||
constexpr int b[3] = {1, 2, 3};
|
||||
static_assert(extract<const int *>(^^b)[2] == 3);
|
||||
|
||||
} // namespace extract_array_as_ptr
|
||||
|
||||
@@ -331,7 +334,7 @@ static_assert([:rvfirst:].first == 1);
|
||||
namespace reflect_constant_callable {
|
||||
|
||||
template<typename T>
|
||||
constexpr auto reflectValueCallable =
|
||||
constexpr auto reflectValueCallable =
|
||||
requires { std::meta::reflect_constant<T>(std::declval<T>()); };
|
||||
|
||||
enum class E {};
|
||||
|
||||
Reference in New Issue
Block a user