Skip to content

Commit aa24802

Browse files
mingxwaclaude
andcommitted
Merge branch 'feature/v5' into user/mingxwa/super-stage5
Resolved the conflict in core.h after extended_overload. This branch had moved diagnose_proxiable_required_convention_not_implemented down next to facade_traits, and #78 removed is_is_direct_well_formed now that static_prop_probe checks is_direct inside the concepts. Neither belongs at that spot any more. #76 removed the converting constructors of the meta storages. The converting constructors of proxy only assign meta_, which #76 kept and extended to an inline storage assigned from a static one, so no further change is needed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 parents 9113554 + a9f488f commit aa24802

3 files changed

Lines changed: 76 additions & 73 deletions

File tree

include/proxy/v4/detail/core.h

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -145,25 +145,21 @@ template <class... Tss>
145145
using merge_tuples_t =
146146
flattening_merge_t<reduction_t<add_tuple_reduction>, Tss...>;
147147

148-
template <class Expr>
149-
consteval bool is_consteval(Expr) {
150-
return requires { typename std::bool_constant<(Expr{}(), false)>; };
151-
}
152-
template <class T, class U>
153-
concept static_prop = std::is_same_v<T, const U&>;
148+
template <class T, auto V>
149+
requires(std::is_same_v<T, decltype(V)>)
150+
struct static_prop_probe;
154151

155152
template <class T, std::size_t I>
156153
concept has_tuple_element = requires { typename std::tuple_element_t<I, T>; };
157154
template <class T>
158155
consteval bool is_tuple_like_well_formed() {
159156
if constexpr (requires {
160-
{ std::tuple_size<T>::value } -> static_prop<std::size_t>;
157+
typename static_prop_probe<std::size_t,
158+
std::tuple_size<T>::value>;
161159
}) {
162-
if constexpr (is_consteval([] { return std::tuple_size<T>::value; })) {
163-
return []<std::size_t... I>(std::index_sequence<I...>) {
164-
return (has_tuple_element<T, I> && ...);
165-
}(std::make_index_sequence<std::tuple_size_v<T>>{});
166-
}
160+
return []<std::size_t... I>(std::index_sequence<I...>) {
161+
return (has_tuple_element<T, I> && ...);
162+
}(std::make_index_sequence<std::tuple_size_v<T>>{});
167163
}
168164
return false;
169165
}
@@ -486,25 +482,13 @@ using substituted_overload_t =
486482
template <class O>
487483
concept extended_overload = overload_traits<O>::applicable ||
488484
overload_substitution_traits<O>::applicable;
489-
template <class T>
490-
consteval bool is_is_direct_well_formed() {
491-
if constexpr (requires {
492-
{ T::is_direct } -> static_prop<bool>;
493-
}) {
494-
if constexpr (is_consteval([] { return T::is_direct; })) {
495-
return true;
496-
}
497-
}
498-
return false;
499-
}
500485

501486
template <class C>
502-
concept basic_convention =
503-
requires {
504-
{ typename C::dispatch_type() } noexcept;
505-
typename C::overload_type;
506-
} && is_is_direct_well_formed<C>() &&
507-
extended_overload<typename C::overload_type>;
487+
concept basic_convention = requires {
488+
{ typename C::dispatch_type() } noexcept;
489+
typename C::overload_type;
490+
typename static_prop_probe<bool, C::is_direct>;
491+
} && extended_overload<typename C::overload_type>;
508492

509493
template <class M>
510494
concept basic_meta =
@@ -518,7 +502,8 @@ concept meta = basic_meta<M> &&
518502
template <class R>
519503
concept basic_reflection = requires {
520504
typename R::reflector_type;
521-
} && is_is_direct_well_formed<R>() && basic_meta<typename R::reflector_type>;
505+
typename static_prop_probe<bool, R::is_direct>;
506+
} && basic_meta<typename R::reflector_type>;
522507

523508
template <class T>
524509
concept pointer_like = (std::is_pointer_v<T> ||
@@ -803,21 +788,18 @@ consteval bool is_cl_well_formed(constraint_level cl) {
803788
template <class F>
804789
consteval bool is_facade_constraints_well_formed() {
805790
if constexpr (requires {
806-
{ F::max_size } -> static_prop<std::size_t>;
807-
{ F::max_align } -> static_prop<std::size_t>;
808-
{ F::copyability } -> static_prop<constraint_level>;
809-
{ F::relocatability } -> static_prop<constraint_level>;
810-
{ F::destructibility } -> static_prop<constraint_level>;
791+
typename static_prop_probe<std::size_t, F::max_size>;
792+
typename static_prop_probe<std::size_t, F::max_align>;
793+
typename static_prop_probe<constraint_level, F::copyability>;
794+
typename static_prop_probe<constraint_level,
795+
F::relocatability>;
796+
typename static_prop_probe<constraint_level,
797+
F::destructibility>;
811798
}) {
812-
if constexpr (is_consteval([] {
813-
return std::tuple{F::max_size, F::max_align, F::copyability,
814-
F::relocatability, F::destructibility};
815-
})) {
816-
return is_layout_well_formed(F::max_size, F::max_align) &&
817-
is_cl_well_formed(F::copyability) &&
818-
is_cl_well_formed(F::relocatability) &&
819-
is_cl_well_formed(F::destructibility);
820-
}
799+
return is_layout_well_formed(F::max_size, F::max_align) &&
800+
is_cl_well_formed(F::copyability) &&
801+
is_cl_well_formed(F::relocatability) &&
802+
is_cl_well_formed(F::destructibility);
821803
}
822804
return false;
823805
}

include/proxy/v4/detail/facade_meta_traits.h

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -140,44 +140,18 @@ struct invoker;
140140
PRO4D_DEF_OVERLOAD_SPECIALIZATIONS(PRO4D_DEF_INVOKER)
141141
#undef PRO4D_DEF_INVOKER
142142

143-
template <class M>
144-
struct PRO4D_ENFORCE_EBO inplace_meta_storage : M {
145-
using M::M;
146-
147-
inplace_meta_storage() = default;
148-
inplace_meta_storage(const inplace_meta_storage&) = default;
149-
template <class M2>
150-
requires(std::is_nothrow_convertible_v<const M2&, const M&>)
151-
inplace_meta_storage(const inplace_meta_storage<M2>& rhs) noexcept
152-
: M(static_cast<const M&>(*rhs)) {}
153-
inplace_meta_storage& operator=(const inplace_meta_storage&) = default;
154-
template <class M2>
155-
requires(std::is_nothrow_convertible_v<const M2&, const M&>)
156-
inplace_meta_storage&
157-
operator=(const inplace_meta_storage<M2>& rhs) noexcept {
158-
static_cast<M&>(*this) = static_cast<const M&>(*rhs);
159-
return *this;
160-
}
161-
162-
const M& operator*() const noexcept { return *this; }
163-
};
164-
165143
template <class M>
166144
struct static_meta_storage {
167145
static_meta_storage() = default;
168-
template <class M2>
169-
requires(std::is_nothrow_convertible_v<const M2&, const M&>)
170-
static_meta_storage(const static_meta_storage<M2>& rhs) noexcept
171-
: ptr_(std::addressof(static_cast<const M&>(*rhs))) {}
146+
template <class P>
147+
explicit static_meta_storage(std::in_place_type_t<P>)
148+
: ptr_(std::addressof(storage<P>)) {}
172149
template <class M2>
173150
requires(std::is_nothrow_convertible_v<const M2&, const M&>)
174151
static_meta_storage& operator=(const static_meta_storage<M2>& rhs) noexcept {
175152
ptr_ = std::addressof(static_cast<const M&>(*rhs));
176153
return *this;
177154
}
178-
template <class P>
179-
explicit static_meta_storage(std::in_place_type_t<P>)
180-
: ptr_(std::addressof(storage<P>)) {}
181155
bool has_value() const noexcept { return ptr_ != nullptr; }
182156
void reset() noexcept { ptr_ = nullptr; }
183157
const M& operator*() const noexcept { return *ptr_; }
@@ -189,6 +163,27 @@ struct static_meta_storage {
189163
static inline const M storage{std::in_place_type<P>};
190164
};
191165

166+
template <class M>
167+
struct inplace_meta_storage : M {
168+
using M::M;
169+
170+
template <class M2>
171+
requires(std::is_nothrow_convertible_v<const M2&, const M&>)
172+
inplace_meta_storage&
173+
operator=(const inplace_meta_storage<M2>& rhs) noexcept {
174+
M::operator=(*rhs);
175+
return *this;
176+
}
177+
template <class M2>
178+
requires(std::is_nothrow_convertible_v<const M2&, const M&>)
179+
inplace_meta_storage& operator=(const static_meta_storage<M2>& rhs) noexcept {
180+
M::operator=(*rhs);
181+
return *this;
182+
}
183+
184+
const M& operator*() const noexcept { return *this; }
185+
};
186+
192187
} // namespace detail
193188

194189
struct compact_facade_meta_traits {

tests/proxy_lifetime_tests.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,32 @@ TEST(ProxyLifetimeTests, Test_CopySubstitution_FromNull) {
12961296
ASSERT_FALSE(p2.has_value());
12971297
}
12981298

1299+
TEST(ProxyLifetimeTests, Test_CopySubstitution_MixedMetaStorage) {
1300+
struct Super : pro::facade_builder //
1301+
::add_convention<utils::spec::FreeToString,
1302+
std::string() const> //
1303+
::support_copy<pro::constraint_level::trivial> //
1304+
::support_relocation<pro::constraint_level::trivial> //
1305+
::support_destruction<pro::constraint_level::trivial> //
1306+
::build {};
1307+
struct Derived : pro::facade_builder //
1308+
::add_facade_with_substitution<Super> //
1309+
::build {};
1310+
static_assert(
1311+
pro::detail::specialization_of<pro::compact_facade_meta_traits::storage<
1312+
pro::detail::proxy_meta<Super>>,
1313+
pro::detail::inplace_meta_storage>);
1314+
static_assert(
1315+
pro::detail::specialization_of<pro::compact_facade_meta_traits::storage<
1316+
pro::detail::proxy_meta<Derived>>,
1317+
pro::detail::static_meta_storage>);
1318+
int v = 123;
1319+
pro::proxy<Derived> p1 = &v;
1320+
pro::proxy<Super> p2 = p1;
1321+
ASSERT_EQ(ToString(*p1), "123");
1322+
ASSERT_EQ(ToString(*p2), "123");
1323+
}
1324+
12991325
TEST(ProxyLifetimeTests, Test_MoveSubstitution_FromValue) {
13001326
utils::LifetimeTracker tracker;
13011327
std::vector<utils::LifetimeOperation> expected_ops;

0 commit comments

Comments
 (0)