@@ -41,7 +41,7 @@ template <class F>
4141struct basic_facade_traits ;
4242
4343template <class F >
44- struct meta_storage ;
44+ struct proxy_meta ;
4545
4646} // namespace detail
4747
@@ -246,15 +246,14 @@ struct proxy_helper {
246246 proxy<F>& p_;
247247 };
248248
249- template <class F >
250- static const meta_storage<F> & get_meta (const proxy<F>& p) noexcept {
251- assert (p.has_value ());
252- return p.meta_ ;
249+ template <class M , class F >
250+ static const M & get_meta (const proxy<F>& p) noexcept {
251+ assert (p.meta_ . has_value ());
252+ return * p.meta_ ;
253253 }
254- template <class F >
255- static const meta_storage<F>&
256- get_meta (const proxy_indirect_accessor<F>& p) noexcept {
257- return get_meta (as_proxy<F, qualifier_type::const_lv>(p));
254+ template <class M , class F >
255+ static const M& get_meta (const proxy_indirect_accessor<F>& p) noexcept {
256+ return get_meta<M>(as_proxy<F, qualifier_type::const_lv>(p));
258257 }
259258 template <class F >
260259 static void * get_ptr (proxy<F>& p) noexcept {
@@ -659,6 +658,122 @@ struct specialization_traits<TT<Args...>, TT> : applicable_traits {};
659658template <class T , template <class ...> class TT >
660659concept specialization_of = specialization_traits<T, TT >::applicable;
661660
661+ template <class O , class I , class T >
662+ struct first_containing_reduction : std::type_identity<O> {};
663+ template <class I , class T >
664+ struct first_containing_reduction <void , I, T>
665+ : std::conditional<std::is_nothrow_convertible_v<const I&, const T&>, I,
666+ void > {};
667+
668+ template <class O , class I >
669+ struct most_containing_reduction
670+ : std::conditional<std::is_nothrow_convertible_v<const I&, const O&>, I,
671+ O> {};
672+ template <class SFINAE , class O , class I >
673+ struct sfinae_unique_types_traits : std::type_identity<O> {};
674+ template <class ... Ts, class U , class ... Us>
675+ struct sfinae_unique_types_traits <
676+ std::enable_if_t <(std::is_nothrow_convertible_v<const Ts&, const U&> ||
677+ ...)>,
678+ std::tuple<Ts...>, std::tuple<U, Us...>>
679+ : sfinae_unique_types_traits<void , std::tuple<Ts...>, std::tuple<Us...>> {};
680+ template <class ... Ts, class U , class ... Us>
681+ struct sfinae_unique_types_traits <
682+ std::enable_if_t <!(std::is_nothrow_convertible_v<const Ts&, const U&> ||
683+ ...)>,
684+ std::tuple<Ts...>, std::tuple<U, Us...>>
685+ : sfinae_unique_types_traits<
686+ void ,
687+ std::tuple<Ts...,
688+ recursive_reduction_t <
689+ reduction_t <most_containing_reduction>, U, Us...>>,
690+ std::tuple<Us...>> {};
691+ template <class T >
692+ using unique_types_t = sfinae_unique_types_traits<void , std::tuple<>, T>::type;
693+
694+ template <class T >
695+ concept nullable = requires (T v, const T cv) {
696+ { v.reset () } noexcept ;
697+ { cv.has_value () } noexcept -> std::same_as<bool >;
698+ };
699+
700+ struct sentinel_meta {
701+ sentinel_meta () = default ;
702+ template <class P >
703+ constexpr explicit sentinel_meta (std::in_place_type_t <P>) noexcept : v_(1 ) {}
704+ void reset () noexcept { v_ = 0 ; }
705+ bool has_value () const noexcept { return v_; }
706+
707+ private:
708+ std::ptrdiff_t v_;
709+ };
710+
711+ template <class ... Ms>
712+ struct PRO4D_ENFORCE_EBO composite_meta : Ms... {
713+ composite_meta () = default ;
714+ template <class P >
715+ constexpr explicit composite_meta (std::in_place_type_t <P>)
716+ : Ms(std::in_place_type<P>)... {}
717+ };
718+
719+ template <nullable First, class ... Rest>
720+ struct proxy_meta_base_impl {
721+ constexpr proxy_meta_base_impl () noexcept {}
722+ template <class P >
723+ constexpr explicit proxy_meta_base_impl (std::in_place_type_t <P>)
724+ : value_(std::in_place_type<P>) {}
725+ proxy_meta_base_impl (const proxy_meta_base_impl& rhs) noexcept
726+ : proxy_meta_base_impl() {
727+ assign (rhs);
728+ }
729+ proxy_meta_base_impl& operator =(const proxy_meta_base_impl& rhs) noexcept {
730+ assign (rhs);
731+ return *this ;
732+ }
733+
734+ template <class T >
735+ requires (std::is_nothrow_convertible_v<const First&, const T&> ||
736+ (std::is_nothrow_convertible_v<const Rest&, const T&> || ...))
737+ constexpr operator const T&() const noexcept {
738+ return static_cast <const recursive_reduction_t <
739+ reduction_t <first_containing_reduction, T>, void , First, Rest...>&>(
740+ value_);
741+ }
742+
743+ bool has_value () const noexcept {
744+ return static_cast <const First&>(value_).has_value ();
745+ }
746+ void reset () noexcept { static_cast <First&>(value_).reset (); }
747+
748+ private:
749+ void assign (const proxy_meta_base_impl& rhs) noexcept {
750+ if (rhs.has_value ()) {
751+ value_ = rhs.value_ ;
752+ } else {
753+ reset ();
754+ }
755+ }
756+
757+ composite_meta<First, Rest...> value_;
758+ };
759+ template <nullable First>
760+ requires (std::is_trivially_copyable_v<First>)
761+ struct proxy_meta_base_impl <First> : First {
762+ using First::First;
763+ };
764+
765+ template <class ... Ms>
766+ struct proxy_meta_base_traits
767+ : specialization_type_traits<proxy_meta_base_impl,
768+ unique_types_t <std::tuple<Ms...>>,
769+ sentinel_meta> {};
770+ template <nullable M, class ... Ms>
771+ struct proxy_meta_base_traits <M, Ms...>
772+ : specialization_type_traits<proxy_meta_base_impl,
773+ unique_types_t <std::tuple<M, Ms...>>> {};
774+ template <class ... Ms>
775+ using proxy_meta_base_t = typename proxy_meta_base_traits<Ms...>::type;
776+
662777template <class P , class F , std::size_t ActualSize, std::size_t MaxSize>
663778consteval void diagnose_proxiable_size_too_large () {
664779 static_assert (ActualSize <= MaxSize, " not proxiable due to size too large" );
@@ -803,8 +918,8 @@ struct facade_traits : specialization_t<facade_conv_traits_impl,
803918 typename F::convention_types, F>,
804919 specialization_t <facade_refl_traits_impl,
805920 typename F::reflection_types, F> {
806- using meta_storage_base = specialization_t <
807- compact_facade_meta_traits::storage ,
921+ using meta_base = specialization_t <
922+ proxy_meta_base_t ,
808923 composite_t <std::tuple<>,
809924 lifetime_meta_t <copy_dispatch, void (void *) const noexcept ,
810925 void (void *) const , F::copyability>,
@@ -849,8 +964,8 @@ struct facade_traits : specialization_t<facade_conv_traits_impl,
849964};
850965
851966template <class F >
852- struct meta_storage : facade_traits<F>::meta_storage_base {
853- using base = facade_traits<F>::meta_storage_base ;
967+ struct proxy_meta : facade_traits<F>::meta_base {
968+ using base = facade_traits<F>::meta_base ;
854969 using base::base;
855970};
856971
@@ -889,7 +1004,7 @@ template <class F, bool IsDirect, class D, class O, class P, class... Args>
8891004ret_t <O> invoke_impl (P&& p, Args&&... args) {
8901005 using Ctx = erased_context<IsDirect, D, O>;
8911006 Ctx ctx{proxy_helper::get_ptr (p)};
892- const auto & inv = proxy_helper::get_meta (p). template get <invoker<Ctx, O>>();
1007+ const auto & inv = proxy_helper::get_meta<invoker<Ctx, O>>(p );
8931008 if constexpr (overload_traits<O>::this_qualifier == qualifier_type::rv) {
8941009 proxy_helper::meta_resetting_guard<F> guard{p};
8951010 return inv (ctx, std::forward<Args>(args)...);
@@ -935,8 +1050,7 @@ class proxy_indirect_accessor
9351050 }
9361051 template <class R >
9371052 friend const R& reflect (const proxy_indirect_accessor& p) noexcept {
938- return detail::proxy_helper::get_meta (p)
939- .template get <detail::reflection_meta<false , R>>()
1053+ return detail::proxy_helper::get_meta<detail::reflection_meta<false , R>>(p)
9401054 .reflector ;
9411055 }
9421056};
@@ -1153,8 +1267,7 @@ class proxy : public detail::facade_traits<F>::direct_accessor,
11531267 }
11541268 template <class R >
11551269 friend const R& reflect (const proxy& p) noexcept {
1156- return detail::proxy_helper::get_meta (p)
1157- .template get <detail::reflection_meta<true , R>>()
1270+ return detail::proxy_helper::get_meta<detail::reflection_meta<true , R>>(p)
11581271 .reflector ;
11591272 }
11601273
@@ -1206,7 +1319,7 @@ class proxy : public detail::facade_traits<F>::direct_accessor,
12061319 P& result = *std::construct_at (reinterpret_cast <P*>(ptr_),
12071320 std::forward<Args>(args)...);
12081321 if constexpr (proxiable<P, F>) {
1209- meta_ = detail::meta_storage<F> {std::in_place_type<P>};
1322+ meta_ = decltype (meta_) {std::in_place_type<P>};
12101323 } else {
12111324 detail::facade_traits<F>::template diagnose_proxiable_noreturn<P>();
12121325 }
@@ -1234,7 +1347,8 @@ class proxy : public detail::facade_traits<F>::direct_accessor,
12341347 })
12351348
12361349 alignas (F::max_align) std::byte ptr_[F::max_size];
1237- detail::meta_storage<F> meta_;
1350+ typename compact_facade_meta_traits::template storage<detail::proxy_meta<F>>
1351+ meta_;
12381352};
12391353
12401354template <class D , class O , facade F, class ... Args>
0 commit comments