@@ -450,30 +450,37 @@ struct lifetime_meta_traits<MP, constraint_level::nontrivial>
450450template <template <bool > class MP , constraint_level C>
451451using lifetime_meta_t = typename lifetime_meta_traits<MP, C>::type;
452452
453+ template <class F > struct proxy_indirect_accessor ;
453454template <class ... As>
454455class ___PRO_ENFORCE_EBO composite_accessor_impl : public As... {
455456 template <class > friend class pro ::proxy;
457+ template <class F > friend struct proxy_indirect_accessor ;
456458
457459 composite_accessor_impl () noexcept = default ;
458460 composite_accessor_impl (const composite_accessor_impl&) noexcept = default ;
459461 composite_accessor_impl& operator =(const composite_accessor_impl&) noexcept
460462 = default ;
461463};
462464
465+ template <class T >
466+ struct accessor_traits_impl : std::type_identity<void > {};
467+ template <class T >
468+ requires (std::is_nothrow_default_constructible_v<T> &&
469+ std::is_trivially_copyable_v<T> && !std::is_final_v<T>)
470+ struct accessor_traits_impl <T> : std::type_identity<T> {};
463471template <class SFINAE , class T , class ... Args>
464472struct sfinae_accessor_traits : std::type_identity<void > {};
465473template <class T , class ... Args>
466474struct sfinae_accessor_traits <
467475 std::void_t <typename T::template accessor<Args...>>, T, Args...>
468- : std::type_identity <typename T::template accessor<Args...>> {};
476+ : accessor_traits_impl <typename T::template accessor<Args...>> {};
469477template <class T , class ... Args>
470478using accessor_t = typename sfinae_accessor_traits<void , T, Args...>::type;
471479
472480template <bool IS_DIRECT, class F , class O , class I >
473481struct composite_accessor_reduction : std::type_identity<O> {};
474482template <bool IS_DIRECT, class F , class ... As, class I >
475- requires (IS_DIRECT == I::is_direct && std::is_trivial_v<accessor_t <I, F>> &&
476- !std::is_final_v<accessor_t <I, F>>)
483+ requires (IS_DIRECT == I::is_direct && !std::is_void_v<accessor_t <I, F>>)
477484struct composite_accessor_reduction <
478485 IS_DIRECT, F, composite_accessor_impl<As...>, I>
479486 { using type = composite_accessor_impl<As..., accessor_t <I, F>>; };
@@ -508,7 +515,6 @@ consteval bool is_facade_constraints_well_formed() {
508515 }
509516 return false ;
510517}
511- struct empty_proxy_base {};
512518template <class F , class ... Cs>
513519struct facade_conv_traits_impl : inapplicable_traits {};
514520template <class F , class ... Cs> requires (conv_traits<Cs>::applicable && ...)
@@ -563,12 +569,14 @@ struct facade_traits<F>
563569 using direct_accessor = merged_composite_accessor<
564570 typename facade_traits::conv_direct_accessor,
565571 typename facade_traits::refl_direct_accessor>;
566- using base = std::conditional_t <std::is_same_v<direct_accessor,
567- composite_accessor_impl<>>, empty_proxy_base, direct_accessor>;
568572 static constexpr bool has_indirection = !std::is_same_v<
569573 typename facade_traits::indirect_accessor, composite_accessor_impl<>>;
570574};
571575
576+ template <class F > struct proxy_indirect_accessor {};
577+ template <class F > requires (facade_traits<F>::has_indirection)
578+ struct proxy_indirect_accessor<F> : facade_traits<F>::indirect_accessor {};
579+
572580using ptr_prototype = void *[2 ];
573581
574582template <class M >
@@ -672,14 +680,32 @@ concept proxiable = facade<F> && sizeof(P) <= F::constraints.max_size &&
672680 details::facade_traits<F>::template refl_applicable_ptr<P>;
673681
674682template <class F >
675- class proxy : public details ::facade_traits<F>::base {
683+ class proxy : public details ::facade_traits<F>::direct_accessor {
676684 static_assert (facade<F>);
677685 friend struct details ::proxy_helper<F>;
678686 using _Traits = details::facade_traits<F>;
687+ using _IA = details::proxy_indirect_accessor<F>;
679688
680689 public:
690+ #ifdef NDEBUG
681691 proxy () noexcept = default;
682- proxy (std::nullptr_t ) noexcept {}
692+ #else
693+ proxy () noexcept {
694+ if constexpr (_Traits::has_indirection) {
695+ std::ignore = static_cast <_IA* (proxy::*)() noexcept >(&proxy::operator ->);
696+ std::ignore = static_cast <const _IA* (proxy::*)() const noexcept >(
697+ &proxy::operator ->);
698+ std::ignore = static_cast <_IA& (proxy::*)() & noexcept >(&proxy::operator *);
699+ std::ignore = static_cast <const _IA& (proxy::*)() const & noexcept >(
700+ &proxy::operator *);
701+ std::ignore = static_cast <_IA&& (proxy::*)() && noexcept >(
702+ &proxy::operator *);
703+ std::ignore = static_cast <const _IA&& (proxy::*)() const && noexcept >(
704+ &proxy::operator *);
705+ }
706+ }
707+ #endif // NDEBUG
708+ proxy (std::nullptr_t ) noexcept : proxy() {}
683709 proxy (const proxy&) noexcept requires (F::constraints.copyability ==
684710 constraint_level::trivial) = default;
685711 proxy (const proxy& rhs)
@@ -709,20 +735,20 @@ class proxy : public details::facade_traits<F>::base {
709735 template <class P >
710736 proxy (P&& ptr) noexcept (std::is_nothrow_constructible_v<std::decay_t <P>, P>)
711737 requires (proxiable<std::decay_t <P>, F> &&
712- std::is_constructible_v<std::decay_t <P>, P>)
738+ std::is_constructible_v<std::decay_t <P>, P>) : proxy()
713739 { initialize<std::decay_t <P>>(std::forward<P>(ptr)); }
714740 template <proxiable<F> P, class ... Args>
715741 explicit proxy (std::in_place_type_t <P>, Args&&... args)
716742 noexcept (std::is_nothrow_constructible_v<P, Args...>)
717- requires(std::is_constructible_v<P, Args...>)
743+ requires(std::is_constructible_v<P, Args...>) : proxy()
718744 { initialize<P>(std::forward<Args>(args)...); }
719745 template <proxiable<F> P, class U , class ... Args>
720746 explicit proxy (std::in_place_type_t <P>, std::initializer_list<U> il,
721747 Args&&... args)
722748 noexcept (std::is_nothrow_constructible_v<
723749 P, std::initializer_list<U>&, Args...>)
724750 requires(std::is_constructible_v<P, std::initializer_list<U>&, Args...>)
725- { initialize<P>(il, std::forward<Args>(args)...); }
751+ : proxy() { initialize<P>(il, std::forward<Args>(args)...); }
726752 proxy& operator =(std::nullptr_t )
727753 noexcept (F::constraints.destructibility >= constraint_level::nothrow)
728754 requires (F::constraints.destructibility >= constraint_level::nontrivial)
@@ -826,18 +852,18 @@ class proxy : public details::facade_traits<F>::base {
826852 requires(std::is_constructible_v<P, std::initializer_list<U>&, Args...> &&
827853 F::constraints.destructibility >= constraint_level::nontrivial)
828854 { reset (); return initialize<P>(il, std::forward<Args>(args)...); }
829- auto operator ->() noexcept requires (_Traits::has_indirection)
855+ _IA* operator ->() noexcept requires (_Traits::has_indirection)
830856 { return std::addressof (ia_); }
831- auto operator ->() const noexcept requires (_Traits::has_indirection)
857+ const _IA* operator ->() const noexcept requires (_Traits::has_indirection)
832858 { return std::addressof (ia_); }
833- auto & operator *() & noexcept requires (_Traits::has_indirection)
859+ _IA & operator *() & noexcept requires (_Traits::has_indirection)
834860 { return ia_; }
835- auto & operator *() const & noexcept requires (_Traits::has_indirection)
861+ const _IA & operator *() const & noexcept requires (_Traits::has_indirection)
836862 { return ia_; }
837- auto && operator *() && noexcept requires (_Traits::has_indirection)
838- { return std::forward<typename _Traits::indirect_accessor >(ia_); }
839- auto && operator *() const && noexcept requires (_Traits::has_indirection)
840- { return std::forward<const typename _Traits::indirect_accessor >(ia_); }
863+ _IA && operator *() && noexcept requires (_Traits::has_indirection)
864+ { return std::forward<_IA >(ia_); }
865+ const _IA && operator *() const && noexcept requires (_Traits::has_indirection)
866+ { return std::forward<const _IA >(ia_); }
841867
842868 friend void swap (proxy& lhs, proxy& rhs) noexcept (noexcept (lhs.swap(rhs)))
843869 { lhs.swap (rhs); }
@@ -856,7 +882,7 @@ class proxy : public details::facade_traits<F>::base {
856882 }
857883
858884 [[___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE]]
859- typename _Traits::indirect_accessor ia_;
885+ _IA ia_;
860886 details::meta_ptr<typename _Traits::meta> meta_;
861887 alignas (F::constraints.max_align) std::byte ptr_[F::constraints.max_size];
862888};
@@ -1107,9 +1133,9 @@ proxy<F> make_proxy(T&& value) {
11071133 struct ___PRO_ENFORCE_EBO accessor { accessor() = delete ; }; \
11081134 template <class __F , class __C , class ... __Os> \
11091135 requires (sizeof ...(__Os) > 1u && \
1110- (::std::is_trivial_v <accessor<__F, __C, __Os>> && ...)) \
1136+ (::std::is_constructible_v <accessor<__F, __C, __Os>> && ...)) \
11111137 struct accessor <__F, __C, __Os...> : accessor<__F, __C, __Os>... \
1112- { using accessor<__F, __C, __Os>:: __VA_ARGS__ ...; }; \
1138+ { using accessor<__F, __C, __Os>::__VA_ARGS__...; }; \
11131139 __MACRO (, *this , __VA_ARGS__); \
11141140 __MACRO (noexcept , *this , __VA_ARGS__); \
11151141 __MACRO (&, *this , __VA_ARGS__); \
@@ -1129,7 +1155,7 @@ proxy<F> make_proxy(T&& value) {
11291155 struct ___PRO_ENFORCE_EBO accessor { accessor() = delete ; }; \
11301156 template <class __F , class __C , class ... __Os> \
11311157 requires (sizeof ...(__Os) > 1u && \
1132- (::std::is_trivial_v <accessor<__F, __C, __Os>> && ...)) \
1158+ (::std::is_constructible_v <accessor<__F, __C, __Os>> && ...)) \
11331159 struct accessor <__F, __C, __Os...> : accessor<__F, __C, __Os>... {}; \
11341160 __MACRO (,, accessor& __self, __self, __VA_ARGS__); \
11351161 __MACRO (noexcept , noexcept , accessor& __self, __self, __VA_ARGS__); \
@@ -1150,6 +1176,13 @@ proxy<F> make_proxy(T&& value) {
11501176 __MACRO (const && noexcept , noexcept , const accessor&& __self, \
11511177 ::std::forward<const accessor>(__self), __VA_ARGS__);
11521178
1179+ #ifdef NDEBUG
1180+ #define ___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR (...)
1181+ #else
1182+ #define ___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR (...) \
1183+ accessor () noexcept { ::std::ignore = &accessor::__VA_ARGS__; }
1184+ #endif // NDEBUG
1185+
11531186namespace details {
11541187
11551188constexpr std::size_t invalid_size = std::numeric_limits<std::size_t >::max();
@@ -1227,6 +1260,7 @@ struct facade_impl {
12271260#define ___PRO_DEF_UPWARD_CONVERSION_ACCESSOR (Q, SELF, ...) \
12281261 template <class F2 , class C > \
12291262 struct accessor <F2, C, proxy<F>() Q> { \
1263+ ___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR (__VA_ARGS__) \
12301264 __VA_ARGS__ () Q { \
12311265 if (access_proxy<F2>(SELF).has_value ()) { \
12321266 return proxy_invoke<C, proxy<F>() Q>(access_proxy<F2>(SELF)); \
@@ -1389,12 +1423,14 @@ struct operator_dispatch;
13891423#define ___PRO_DEF_LHS_LEFT_OP_ACCESSOR (Q, SELF, ...) \
13901424 template <class F , class C , class R > \
13911425 struct accessor <F, C, R() Q> { \
1426+ ___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR (__VA_ARGS__) \
13921427 R __VA_ARGS__ () Q \
13931428 { return proxy_invoke<C, R () Q>(access_proxy<F>(SELF)); } \
13941429 }
13951430#define ___PRO_DEF_LHS_ANY_OP_ACCESSOR (Q, SELF, ...) \
13961431 template <class F , class C , class R , class ... Args> \
13971432 struct accessor <F, C, R(Args...) Q> { \
1433+ ___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR (__VA_ARGS__) \
13981434 R __VA_ARGS__ (Args... args) Q { \
13991435 return proxy_invoke<C, R (Args...) Q>( \
14001436 access_proxy<F>(SELF), std::forward<Args>(args)...); \
@@ -1460,6 +1496,7 @@ struct operator_dispatch;
14601496#define ___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR (Q, SELF, ...) \
14611497 template <class F , class C , class R , class Arg > \
14621498 struct accessor <F, C, R(Arg) Q> { \
1499+ ___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR (__VA_ARGS__) \
14631500 decltype (auto ) __VA_ARGS__ (Arg arg) Q { \
14641501 proxy_invoke<C, R (Arg) Q>( \
14651502 access_proxy<F>(SELF), std::forward<Arg>(arg)); \
@@ -1577,6 +1614,7 @@ struct operator_dispatch<"[]", false> {
15771614#define ___PRO_DEF_CONVERSION_ACCESSOR (Q, SELF, ...) \
15781615 template <class F , class C > \
15791616 struct accessor <F, C, T() Q> { \
1617+ ___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR (__VA_ARGS__) \
15801618 explicit (Expl) __VA_ARGS__ () Q \
15811619 { return proxy_invoke<C, T () Q>(access_proxy<F>(SELF)); } \
15821620 }
@@ -1604,6 +1642,7 @@ struct conversion_dispatch {
16041642#define ___PRO_DEF_MEM_ACCESSOR (__Q, __SELF, ...) \
16051643 template <class __F , class __C , class __R , class ... __Args> \
16061644 struct accessor <__F, __C, __R(__Args...) __Q> { \
1645+ ___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR (__VA_ARGS__) \
16071646 __R __VA_ARGS__ (__Args... __args) __Q { \
16081647 return ::pro::proxy_invoke<__C, __R (__Args...) __Q>( \
16091648 ::pro::access_proxy<__F>(__SELF), \
0 commit comments