@@ -198,25 +198,24 @@ class destruction_guard {
198198 T* p_;
199199};
200200
201- template <class P , qualifier_type Q, bool NE >
202- struct ptr_traits : inapplicable_traits {};
203- template <class P , qualifier_type Q, bool NE >
204- requires ( requires { *std::declval< add_qualifier_t < P, Q>>(); } &&
205- (! NE || noexcept ( *std::declval<add_qualifier_t <P, Q>>())))
206- struct ptr_traits <P, Q, NE > : applicable_traits
207- { using target_type = decltype (*std::declval< add_qualifier_t < P, Q>>()); } ;
201+ template <bool IsDirect, class P , qualifier_type Q>
202+ struct operand_traits : add_qualifier_traits<P, Q> {};
203+ template <class P , qualifier_type Q>
204+ struct operand_traits < false , P, Q>
205+ : std::type_identity< decltype ( *std::declval<add_qualifier_t <P, Q>>())> {};
206+ template < bool IsDirect, class P , qualifier_type Q>
207+ using operand_t = typename operand_traits<IsDirect, P, Q>::type ;
208208
209209template <class D , bool NE , class R , class ... Args>
210210concept invocable_dispatch = (NE && std::is_nothrow_invocable_r_v<
211211 R, D, Args...>) || (!NE && std::is_invocable_r_v<R, D, Args...>);
212- template <class D , class P , qualifier_type Q, bool NE , class R , class ... Args>
213- concept invocable_dispatch_ptr_indirect = ptr_traits<P, Q, NE >::applicable &&
214- invocable_dispatch<
215- D, NE , R, typename ptr_traits<P, Q, NE >::target_type, Args...>;
216- template <class D , class P , qualifier_type Q, bool NE , class R , class ... Args>
217- concept invocable_dispatch_ptr_direct = invocable_dispatch<
218- D, NE , R, add_qualifier_t <P, Q>, Args...> && (Q != qualifier_type::rv ||
219- (NE && std::is_nothrow_destructible_v<P>) ||
212+ template <bool IsDirect, class D , class P , qualifier_type Q, bool NE , class R ,
213+ class ... Args>
214+ concept invocable_dispatch_ptr =
215+ (IsDirect || (requires { *std::declval<add_qualifier_t <P, Q>>(); } &&
216+ (!NE || noexcept (*std::declval<add_qualifier_t <P, Q>>())))) &&
217+ invocable_dispatch<D, NE , R, operand_t <IsDirect, P, Q>, Args...> &&
218+ (Q != qualifier_type::rv || (NE && std::is_nothrow_destructible_v<P>) ||
220219 (!NE && std::is_destructible_v<P>));
221220
222221template <class D , class R , class ... Args>
@@ -227,25 +226,27 @@ R invoke_dispatch(Args&&... args) {
227226 return D{}(std::forward<Args>(args)...);
228227 }
229228}
230- template <class D , class P , qualifier_type Q, class R , class ... Args>
231- R indirect_conv_dispatcher (add_qualifier_t <std::byte, Q> self, Args... args)
232- noexcept (invocable_dispatch_ptr_indirect<D, P, Q, true , R, Args...>) {
233- auto & qp = *std::launder (reinterpret_cast <add_qualifier_ptr_t <P, Q>>(&self));
234- if constexpr (std::is_constructible_v<bool , decltype (qp)>) { assert (qp); }
235- return invoke_dispatch<D, R>(*std::forward<add_qualifier_t <P, Q>>(qp),
236- std::forward<Args>(args)...);
229+ template <bool IsDirect, class P , qualifier_type Q, class T >
230+ decltype (auto ) get_operand(T& ptr) {
231+ if constexpr (IsDirect) {
232+ return std::forward<add_qualifier_t <P, Q>>(ptr);
233+ } else {
234+ if constexpr (std::is_constructible_v<bool , T&>) { assert (ptr); }
235+ return *std::forward<add_qualifier_t <P, Q>>(ptr);
236+ }
237237}
238- template <class D , class P , qualifier_type Q, class R , class ... Args>
239- R direct_conv_dispatcher (add_qualifier_t <std::byte, Q> self, Args... args)
240- noexcept (invocable_dispatch_ptr_direct<D, P, Q, true , R, Args...>) {
238+ template <bool IsDirect, class D , class P , qualifier_type Q, class R ,
239+ class ... Args>
240+ R conv_dispatcher (add_qualifier_t <std::byte, Q> self, Args... args)
241+ noexcept (invocable_dispatch_ptr<IsDirect, D, P, Q, true , R, Args...>) {
241242 auto & qp = *std::launder (reinterpret_cast <add_qualifier_ptr_t <P, Q>>(&self));
242243 if constexpr (Q == qualifier_type::rv) {
243244 destruction_guard guard{&qp};
244- return invoke_dispatch<D, R>(
245- std::forward<add_qualifier_t <P, Q>>(qp), std::forward< Args>(args)...);
245+ return invoke_dispatch<D, R>(get_operand<IsDirect, P, Q>(qp),
246+ std::forward<Args>(args)...);
246247 } else {
247- return invoke_dispatch<D, R>(
248- std::forward<add_qualifier_t <P, Q>>(qp), std::forward< Args>(args)...);
248+ return invoke_dispatch<D, R>(get_operand<IsDirect, P, Q>(qp),
249+ std::forward<Args>(args)...);
249250 }
250251}
251252template <class D , qualifier_type Q, class R , class ... Args>
@@ -263,28 +264,16 @@ struct overload_traits_impl : applicable_traits {
263264
264265 template <bool IsDirect, class D , class P >
265266 static consteval bool is_applicable_ptr () {
266- if constexpr (IsDirect) {
267- if constexpr (invocable_dispatch_ptr_direct<D, P, Q, NE , R, Args...>) {
268- return true ;
269- } else {
270- return invocable_dispatch<D, NE , R, std::nullptr_t , Args...>;
271- }
267+ if constexpr (invocable_dispatch_ptr<IsDirect, D, P, Q, NE , R, Args...>) {
268+ return true ;
272269 } else {
273- if constexpr (invocable_dispatch_ptr_indirect<D, P, Q, NE , R, Args...>) {
274- return true ;
275- } else {
276- return invocable_dispatch<D, NE , R, std::nullptr_t , Args...>;
277- }
270+ return invocable_dispatch<D, NE , R, std::nullptr_t , Args...>;
278271 }
279272 }
280273 template <bool IsDirect, class D , class P >
281274 static consteval dispatcher_type get_dispatcher () {
282- if constexpr (!IsDirect &&
283- invocable_dispatch_ptr_indirect<D, P, Q, NE , R, Args...>) {
284- return &indirect_conv_dispatcher<D, P, Q, R, Args...>;
285- } else if constexpr (IsDirect &&
286- invocable_dispatch_ptr_direct<D, P, Q, NE , R, Args...>) {
287- return &direct_conv_dispatcher<D, P, Q, R, Args...>;
275+ if constexpr (invocable_dispatch_ptr<IsDirect, D, P, Q, NE , R, Args...>) {
276+ return &conv_dispatcher<IsDirect, D, P, Q, R, Args...>;
288277 } else {
289278 return &default_conv_dispatcher<D, Q, R, Args...>;
290279 }
@@ -791,8 +780,7 @@ struct proxy_helper {
791780 static decltype (auto ) invoke(add_qualifier_t <proxy<F>, Q> p, Args&&... args) {
792781 auto dispatcher = get_meta (p).template invocation_meta <IsDirect, D, O>
793782 ::dispatcher;
794- if constexpr (
795- IsDirect && overload_traits<O>::qualifier == qualifier_type::rv) {
783+ if constexpr (overload_traits<O>::qualifier == qualifier_type::rv) {
796784 meta_ptr_reset_guard guard{p.meta_ };
797785 return dispatcher (std::forward<add_qualifier_t <std::byte, Q>>(*p.ptr_ ),
798786 std::forward<Args>(args)...);
@@ -1327,8 +1315,8 @@ class strong_compact_ptr
13271315 { return std::launder (reinterpret_cast <const T*>(&this ->ptr_ ->value )); }
13281316 T& operator *() & noexcept { return *operator ->(); }
13291317 const T& operator *() const & noexcept { return *operator ->(); }
1330- T&& operator *() && noexcept { return std::move (operator ->()); }
1331- const T&& operator *() const && noexcept { return std::move (operator ->()); }
1318+ T&& operator *() && noexcept { return std::move (* operator ->()); }
1319+ const T&& operator *() const && noexcept { return std::move (* operator ->()); }
13321320
13331321 private:
13341322 explicit strong_compact_ptr (Storage* ptr) noexcept
0 commit comments