diff --git a/proxy.h b/proxy.h
index 2168ba12..165c23e5 100644
--- a/proxy.h
+++ b/proxy.h
@@ -41,6 +41,12 @@
#define ___PRO_THROW(...) std::abort()
#endif // __cpp_exceptions >= 199711L
+#if __cpp_static_call_operator >= 202207L
+#define ___PRO_STATIC_CALL(__R, ...) static __R operator()(__VA_ARGS__)
+#else
+#define ___PRO_STATIC_CALL(__R, ...) __R operator()(__VA_ARGS__) const
+#endif // __cpp_static_call_operator >= 202207L
+
#ifdef _MSC_VER
#define ___PRO_ENFORCE_EBO __declspec(empty_bases)
#else
@@ -213,10 +219,6 @@ concept invocable_dispatch_ptr_direct = invocable_dispatch<
(NE && std::is_nothrow_destructible_v
) ||
(!NE && std::is_destructible_v
));
-template
-using func_ptr_t = std::conditional_t<
- NE, R (*)(Args...) noexcept, R (*)(Args...)>;
-
template
R invoke_dispatch(Args&&... args) {
if constexpr (std::is_void_v) {
@@ -250,52 +252,14 @@ template
R default_conv_dispatcher(add_qualifier_t, Args... args)
noexcept(invocable_dispatch)
{ return invoke_dispatch(nullptr, std::forward(args)...); }
-template
-void copying_dispatcher(std::byte& self, const std::byte& rhs)
- noexcept(has_copyability(constraint_level::nothrow)) {
- std::construct_at(reinterpret_cast
(&self),
- *std::launder(reinterpret_cast(&rhs)));
-}
-template
-void copying_default_dispatcher(std::byte& self, const std::byte& rhs)
- noexcept {
- std::uninitialized_copy_n(
- std::assume_aligned(&rhs), Len, std::assume_aligned(&self));
-}
-template
-void relocation_dispatcher(std::byte& self, const std::byte& rhs)
- noexcept(has_relocatability(constraint_level::nothrow)) {
- P* other = std::launder(reinterpret_cast
(const_cast(&rhs)));
- destruction_guard guard{other};
- std::construct_at(reinterpret_cast(&self), std::move(*other));
-}
-template
-void destruction_dispatcher(std::byte& self)
- noexcept(has_destructibility(constraint_level::nothrow))
- { std::destroy_at(std::launder(reinterpret_cast
(&self))); }
-inline void destruction_default_dispatcher(std::byte&) noexcept {}
template struct overload_traits : inapplicable_traits {};
template
struct overload_traits_impl : applicable_traits {
- template
- struct meta_provider {
- template
- static consteval auto get()
- -> func_ptr_t, Args...> {
- if constexpr (!IsDirect &&
- invocable_dispatch_ptr_indirect) {
- return &indirect_conv_dispatcher;
- } else if constexpr (IsDirect &&
- invocable_dispatch_ptr_direct) {
- return &direct_conv_dispatcher;
- } else {
- return &default_conv_dispatcher;
- }
- }
- };
using return_type = R;
using view_type = R(Args...) const noexcept(NE);
+ using dispatcher_type =
+ R (*)(add_qualifier_t, Args...) noexcept(NE);
template
static consteval bool is_applicable_ptr() {
@@ -306,14 +270,25 @@ struct overload_traits_impl : applicable_traits {
return invocable_dispatch;
}
} else {
- if constexpr (
- invocable_dispatch_ptr_indirect) {
+ if constexpr (invocable_dispatch_ptr_indirect) {
return true;
} else {
return invocable_dispatch;
}
}
}
+ template
+ static consteval dispatcher_type get_dispatcher() {
+ if constexpr (!IsDirect &&
+ invocable_dispatch_ptr_indirect) {
+ return &indirect_conv_dispatcher;
+ } else if constexpr (IsDirect &&
+ invocable_dispatch_ptr_direct) {
+ return &direct_conv_dispatcher;
+ } else {
+ return &default_conv_dispatcher;
+ }
+ }
static constexpr qualifier_type qualifier = Q;
};
@@ -377,14 +352,15 @@ consteval bool diagnose_proxiable_required_convention_not_implemented() {
return verdict;
}
-template
-struct dispatcher_meta {
- constexpr dispatcher_meta() noexcept : dispatcher(nullptr) {}
+template
+struct invocation_meta {
+ constexpr invocation_meta() noexcept : dispatcher(nullptr) {}
template
- constexpr explicit dispatcher_meta(std::in_place_type_t) noexcept
- : dispatcher(MP::template get
()) {}
+ constexpr explicit invocation_meta(std::in_place_type_t
) noexcept
+ : dispatcher(overload_traits
+ ::template get_dispatcher()) {}
- decltype(MP::template get()) dispatcher;
+ typename overload_traits::dispatcher_type dispatcher;
};
template
@@ -439,9 +415,8 @@ struct conv_traits_impl : inapplicable_traits {};
template
requires(overload_traits>::applicable && ...)
struct conv_traits_impl : applicable_traits {
- using meta = composite_meta_impl>::template meta_provider<
- C::is_direct, typename C::dispatch_type>>...>;
+ using meta = composite_meta_impl>...>;
template
static consteval bool diagnose_proxiable() {
@@ -516,49 +491,28 @@ struct refl_traits {
is_reflector_well_formed();
};
-template
-struct copyability_meta_provider {
- template
- static consteval func_ptr_t get() {
- if constexpr (has_copyability(constraint_level::trivial)) {
- return ©ing_default_dispatcher;
- } else {
- return ©ing_dispatcher;
- }
- }
+struct copy_dispatch {
+ template
+ ___PRO_STATIC_CALL(void, T&& self, proxy& rhs)
+ noexcept(std::is_nothrow_constructible_v, T>)
+ requires(std::is_constructible_v, T>)
+ { std::construct_at(&rhs, std::forward(self)); }
};
-template
-struct relocatability_meta_provider {
- template
- static consteval func_ptr_t get() {
- if constexpr (has_relocatability(constraint_level::trivial)) {
- return ©ing_default_dispatcher;
- } else {
- return &relocation_dispatcher;
- }
- }
-};
-template
-struct destructibility_meta_provider {
- template
- static consteval func_ptr_t get() {
- if constexpr (has_destructibility(constraint_level::trivial)) {
- return &destruction_default_dispatcher;
- } else {
- return &destruction_dispatcher
;
- }
- }
+struct destroy_dispatch {
+ template
+ ___PRO_STATIC_CALL(void, T& self) noexcept(std::is_nothrow_destructible_v)
+ requires(std::is_destructible_v) { std::destroy_at(&self); }
};
-template class MP, constraint_level C>
+template
struct lifetime_meta_traits : std::type_identity {};
-template class MP>
-struct lifetime_meta_traits
- : std::type_identity>> {};
-template class MP>
-struct lifetime_meta_traits
- : std::type_identity>> {};
-template class MP, constraint_level C>
-using lifetime_meta_t = typename lifetime_meta_traits::type;
+template
+struct lifetime_meta_traits
+ : std::type_identity> {};
+template
+struct lifetime_meta_traits
+ : std::type_identity> {};
+template
+using lifetime_meta_t = typename lifetime_meta_traits::type;
template
class ___PRO_ENFORCE_EBO composite_accessor_impl : public As... {
@@ -705,9 +659,8 @@ struct facade_conv_traits_impl : applicable_traits {
static constexpr bool conv_applicable_ptr =
(conv_traits::template applicable_ptr && ...);
template
- static constexpr bool is_invocable = std::is_base_of_v::template meta_provider>,
- conv_meta>;
+ static constexpr bool is_invocable = std::is_base_of_v<
+ invocation_meta, conv_meta>;
};
template
struct facade_refl_traits_impl {
@@ -732,15 +685,13 @@ template requires(instantiated_t<
struct facade_traits
: instantiated_t,
instantiated_t {
- using copyability_meta = lifetime_meta_t<
- copyability_meta_provider, F::constraints.copyability>;
- using relocatability_meta = lifetime_meta_t;
- using destructibility_meta = lifetime_meta_t<
- destructibility_meta_provider, F::constraints.destructibility>;
- using meta = composite_meta&) const noexcept,
+ void(proxy&) const, F::constraints.copyability>,
+ lifetime_meta_t&) && noexcept,
+ void(proxy&) &&, F::constraints.relocatability>,
+ lifetime_meta_t, typename facade_traits::conv_meta,
typename facade_traits::refl_meta>;
using indirect_accessor = merged_composite_accessor<
typename facade_traits::conv_indirect_accessor,
@@ -802,10 +753,12 @@ struct meta_ptr_direct_impl : private M {
};
template
struct meta_ptr_traits_impl : std::type_identity> {};
-template
-struct meta_ptr_traits_impl, Ms...>>
+template
+struct meta_ptr_traits_impl<
+ composite_meta_impl, Ms...>>
: std::type_identity, Ms...>, dispatcher_meta>> {};
+ invocation_meta, Ms...>,
+ invocation_meta>> {};
template
struct meta_ptr_traits : std::type_identity> {};
template
@@ -836,9 +789,8 @@ struct proxy_helper {
}
template
static decltype(auto) invoke(add_qualifier_t, Q> p, Args&&... args) {
- auto dispatcher = get_meta(p)
- .template dispatcher_meta
- ::template meta_provider>::dispatcher;
+ auto dispatcher = get_meta(p).template invocation_meta
+ ::dispatcher;
if constexpr (
IsDirect && overload_traits::qualifier == qualifier_type::rv) {
meta_ptr_reset_guard guard{p.meta_};
@@ -931,6 +883,60 @@ template
struct proxy_indirect_accessor : details::facade_traits::indirect_accessor
{ friend class details::inplace_ptr; };
+template
+auto proxy_invoke(proxy& p, Args&&... args)
+ -> typename details::overload_traits::return_type {
+ return details::proxy_helper::template invoke(p, std::forward(args)...);
+}
+template
+auto proxy_invoke(const proxy& p, Args&&... args)
+ -> typename details::overload_traits::return_type {
+ return details::proxy_helper::template invoke(p, std::forward(args)...);
+}
+template
+auto proxy_invoke(proxy&& p, Args&&... args)
+ -> typename details::overload_traits::return_type {
+ return details::proxy_helper::template invoke<
+ IsDirect, D, O, details::qualifier_type::rv>(
+ std::move(p), std::forward(args)...);
+}
+template
+auto proxy_invoke(const proxy&& p, Args&&... args)
+ -> typename details::overload_traits::return_type {
+ return details::proxy_helper::template invoke<
+ IsDirect, D, O, details::qualifier_type::const_rv>(
+ std::move(p), std::forward(args)...);
+}
+
+template
+const R& proxy_reflect(const proxy& p) noexcept {
+ return static_cast&>(
+ details::proxy_helper::get_meta(p)).reflector;
+}
+
+template
+proxy& access_proxy(A& a) noexcept {
+ return details::proxy_helper::template access<
+ A, details::qualifier_type::lv>(a);
+}
+template
+const proxy& access_proxy(const A& a) noexcept {
+ return details::proxy_helper::template access<
+ A, details::qualifier_type::const_lv>(a);
+}
+template
+proxy&& access_proxy(A&& a) noexcept {
+ return details::proxy_helper::template access<
+ A, details::qualifier_type::rv>(std::forward(a));
+}
+template
+const proxy&& access_proxy(const A&& a) noexcept {
+ return details::proxy_helper::template access<
+ A, details::qualifier_type::const_rv>(std::forward(a));
+}
+
template
class proxy : public details::facade_traits::direct_accessor,
public details::inplace_ptr> {
@@ -949,8 +955,8 @@ class proxy : public details::facade_traits::direct_accessor,
F::constraints.copyability == constraint_level::nothrow)
: details::inplace_ptr>() { // Make GCC happy
if (rhs.meta_.has_value()) {
- rhs.meta_->_Traits::copyability_meta::dispatcher(*ptr_, *rhs.ptr_);
- meta_ = rhs.meta_;
+ proxy_invoke(rhs, *this);
}
}
proxy(proxy&& rhs)
@@ -962,10 +968,12 @@ class proxy : public details::facade_traits::direct_accessor,
if constexpr (F::constraints.relocatability ==
constraint_level::trivial) {
std::ranges::uninitialized_copy(rhs.ptr_, ptr_);
+ meta_ = rhs.meta_;
} else {
- rhs.meta_->_Traits::relocatability_meta::dispatcher(*ptr_, *rhs.ptr_);
+ proxy_invoke(
+ std::move(rhs), *this);
}
- meta_ = rhs.meta_;
}
}
template
@@ -1041,8 +1049,10 @@ class proxy : public details::facade_traits::direct_accessor,
~proxy() noexcept(F::constraints.destructibility == constraint_level::nothrow)
requires(F::constraints.destructibility == constraint_level::nontrivial ||
F::constraints.destructibility == constraint_level::nothrow) {
- if (meta_.has_value())
- { meta_->_Traits::destructibility_meta::dispatcher(*ptr_); }
+ if (meta_.has_value()) {
+ proxy_invoke(*this);
+ }
}
bool has_value() const noexcept { return meta_.has_value(); }
@@ -1119,60 +1129,6 @@ ___PRO_DEBUG(
alignas(F::constraints.max_align) std::byte ptr_[F::constraints.max_size];
};
-template
-auto proxy_invoke(proxy& p, Args&&... args)
- -> typename details::overload_traits::return_type {
- return details::proxy_helper::template invoke(p, std::forward(args)...);
-}
-template
-auto proxy_invoke(const proxy& p, Args&&... args)
- -> typename details::overload_traits::return_type {
- return details::proxy_helper::template invoke(p, std::forward(args)...);
-}
-template
-auto proxy_invoke(proxy&& p, Args&&... args)
- -> typename details::overload_traits::return_type {
- return details::proxy_helper::template invoke<
- IsDirect, D, O, details::qualifier_type::rv>(
- std::move(p), std::forward(args)...);
-}
-template
-auto proxy_invoke(const proxy&& p, Args&&... args)
- -> typename details::overload_traits::return_type {
- return details::proxy_helper::template invoke<
- IsDirect, D, O, details::qualifier_type::const_rv>(
- std::move(p), std::forward(args)...);
-}
-
-template
-const R& proxy_reflect(const proxy& p) noexcept {
- return static_cast&>(
- details::proxy_helper::get_meta(p)).reflector;
-}
-
-template
-proxy& access_proxy(A& a) noexcept {
- return details::proxy_helper::template access<
- A, details::qualifier_type::lv>(a);
-}
-template
-const proxy& access_proxy(const A& a) noexcept {
- return details::proxy_helper::template access<
- A, details::qualifier_type::const_lv>(a);
-}
-template
-proxy&& access_proxy(A&& a) noexcept {
- return details::proxy_helper::template access<
- A, details::qualifier_type::rv>(std::forward(a));
-}
-template
-const proxy&& access_proxy(const A&& a) noexcept {
- return details::proxy_helper::template access<
- A, details::qualifier_type::const_rv>(std::forward(a));
-}
-
namespace details {
template
@@ -1583,12 +1539,6 @@ class bad_proxy_cast : public std::bad_cast {
};
#endif // __cpp_rtti >= 199711L
-#if __cpp_static_call_operator >= 202207L
-#define ___PRO_STATIC_CALL(__R, ...) static __R operator()(__VA_ARGS__)
-#else
-#define ___PRO_STATIC_CALL(__R, ...) __R operator()(__VA_ARGS__) const
-#endif // __cpp_static_call_operator >= 202207L
-
#define ___PRO_DIRECT_FUNC_IMPL(...) \
noexcept(noexcept(__VA_ARGS__)) requires(requires { __VA_ARGS__; }) \
{ return __VA_ARGS__; }