proxy.h 88 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194
  1. // Copyright (c) Microsoft Corporation.
  2. // Licensed under the MIT License.
  3. #ifndef _MSFT_PROXY_
  4. #define _MSFT_PROXY_
  5. #include <cassert>
  6. #include <cstddef>
  7. #include <cstdlib>
  8. #include <bit>
  9. #include <concepts>
  10. #include <exception>
  11. #include <initializer_list>
  12. #include <limits>
  13. #include <memory>
  14. #include <tuple>
  15. #include <type_traits>
  16. #include <utility>
  17. #if __STDC_HOSTED__
  18. #include <format>
  19. #endif // __STDC_HOSTED__
  20. #ifdef __cpp_rtti
  21. #include <optional>
  22. #include <typeinfo>
  23. #endif // __cpp_rtti
  24. #if __has_cpp_attribute(msvc::no_unique_address)
  25. #define ___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE msvc::no_unique_address
  26. #elif __has_cpp_attribute(no_unique_address)
  27. #define ___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE no_unique_address
  28. #else
  29. #error "Proxy requires C++20 attribute no_unique_address"
  30. #endif
  31. #ifdef __cpp_exceptions
  32. #define ___PRO_THROW(...) throw __VA_ARGS__
  33. #else
  34. #define ___PRO_THROW(...) std::abort()
  35. #endif // __cpp_exceptions
  36. #ifdef _MSC_VER
  37. #define ___PRO_ENFORCE_EBO __declspec(empty_bases)
  38. #else
  39. #define ___PRO_ENFORCE_EBO
  40. #endif // _MSC_VER
  41. #ifdef NDEBUG
  42. #define ___PRO_DEBUG(...)
  43. #else
  44. #define ___PRO_DEBUG(...) __VA_ARGS__
  45. #endif // NDEBUG
  46. #define __msft_lib_proxy 202501L
  47. namespace pro {
  48. enum class constraint_level { none, nontrivial, nothrow, trivial };
  49. struct proxiable_ptr_constraints {
  50. std::size_t max_size;
  51. std::size_t max_align;
  52. constraint_level copyability;
  53. constraint_level relocatability;
  54. constraint_level destructibility;
  55. };
  56. template <class F> struct proxy_indirect_accessor;
  57. template <class F> class proxy;
  58. namespace details {
  59. struct applicable_traits { static constexpr bool applicable = true; };
  60. struct inapplicable_traits { static constexpr bool applicable = false; };
  61. enum class qualifier_type { lv, const_lv, rv, const_rv };
  62. template <class T, qualifier_type Q> struct add_qualifier_traits;
  63. template <class T>
  64. struct add_qualifier_traits<T, qualifier_type::lv> : std::type_identity<T&> {};
  65. template <class T>
  66. struct add_qualifier_traits<T, qualifier_type::const_lv>
  67. : std::type_identity<const T&> {};
  68. template <class T>
  69. struct add_qualifier_traits<T, qualifier_type::rv> : std::type_identity<T&&> {};
  70. template <class T>
  71. struct add_qualifier_traits<T, qualifier_type::const_rv>
  72. : std::type_identity<const T&&> {};
  73. template <class T, qualifier_type Q>
  74. using add_qualifier_t = typename add_qualifier_traits<T, Q>::type;
  75. template <class T, qualifier_type Q>
  76. using add_qualifier_ptr_t = std::remove_reference_t<add_qualifier_t<T, Q>>*;
  77. template <template <class, class> class R, class O, class... Is>
  78. struct recursive_reduction : std::type_identity<O> {};
  79. template <template <class, class> class R, class O, class I, class... Is>
  80. struct recursive_reduction<R, O, I, Is...>
  81. : recursive_reduction<R, R<O, I>, Is...> {};
  82. template <template <class, class> class R, class O, class... Is>
  83. using recursive_reduction_t = typename recursive_reduction<R, O, Is...>::type;
  84. template <class Expr>
  85. consteval bool is_consteval(Expr)
  86. { return requires { typename std::bool_constant<(Expr{}(), false)>; }; }
  87. template <class T, std::size_t I>
  88. concept has_tuple_element = requires { typename std::tuple_element_t<I, T>; };
  89. template <class T>
  90. consteval bool is_tuple_like_well_formed() {
  91. if constexpr (requires { { std::tuple_size<T>::value } ->
  92. std::same_as<const std::size_t&>; }) {
  93. if constexpr (is_consteval([] { return std::tuple_size<T>::value; })) {
  94. return []<std::size_t... I>(std::index_sequence<I...>) {
  95. return (has_tuple_element<T, I> && ...);
  96. }(std::make_index_sequence<std::tuple_size_v<T>>{});
  97. }
  98. }
  99. return false;
  100. }
  101. template <template <class...> class T, class TL, class Is, class... Args>
  102. struct instantiated_traits;
  103. template <template <class...> class T, class TL, std::size_t... Is,
  104. class... Args>
  105. struct instantiated_traits<T, TL, std::index_sequence<Is...>, Args...>
  106. : std::type_identity<T<Args..., std::tuple_element_t<Is, TL>...>> {};
  107. template <template <class...> class T, class TL, class... Args>
  108. using instantiated_t = typename instantiated_traits<
  109. T, TL, std::make_index_sequence<std::tuple_size_v<TL>>, Args...>::type;
  110. template <class T>
  111. consteval bool has_copyability(constraint_level level) {
  112. switch (level) {
  113. case constraint_level::none: return true;
  114. case constraint_level::nontrivial: return std::is_copy_constructible_v<T>;
  115. case constraint_level::nothrow:
  116. return std::is_nothrow_copy_constructible_v<T>;
  117. case constraint_level::trivial:
  118. return std::is_trivially_copy_constructible_v<T> &&
  119. std::is_trivially_destructible_v<T>;
  120. default: return false;
  121. }
  122. }
  123. template <class T>
  124. consteval bool has_relocatability(constraint_level level) {
  125. switch (level) {
  126. case constraint_level::none: return true;
  127. case constraint_level::nontrivial:
  128. return std::is_move_constructible_v<T> && std::is_destructible_v<T>;
  129. case constraint_level::nothrow:
  130. return std::is_nothrow_move_constructible_v<T> &&
  131. std::is_nothrow_destructible_v<T>;
  132. case constraint_level::trivial:
  133. return std::is_trivially_move_constructible_v<T> &&
  134. std::is_trivially_destructible_v<T>;
  135. default: return false;
  136. }
  137. }
  138. template <class T>
  139. consteval bool has_destructibility(constraint_level level) {
  140. switch (level) {
  141. case constraint_level::none: return true;
  142. case constraint_level::nontrivial: return std::is_destructible_v<T>;
  143. case constraint_level::nothrow: return std::is_nothrow_destructible_v<T>;
  144. case constraint_level::trivial: return std::is_trivially_destructible_v<T>;
  145. default: return false;
  146. }
  147. }
  148. template <class T>
  149. class destruction_guard {
  150. public:
  151. explicit destruction_guard(T* p) noexcept : p_(p) {}
  152. destruction_guard(const destruction_guard&) = delete;
  153. ~destruction_guard() noexcept(std::is_nothrow_destructible_v<T>)
  154. { std::destroy_at(p_); }
  155. private:
  156. T* p_;
  157. };
  158. template <class P, qualifier_type Q, bool NE>
  159. struct ptr_traits : inapplicable_traits {};
  160. template <class P, qualifier_type Q, bool NE>
  161. requires(requires { *std::declval<add_qualifier_t<P, Q>>(); } &&
  162. (!NE || noexcept(*std::declval<add_qualifier_t<P, Q>>())))
  163. struct ptr_traits<P, Q, NE> : applicable_traits
  164. { using target_type = decltype(*std::declval<add_qualifier_t<P, Q>>()); };
  165. template <class D, bool NE, class R, class... Args>
  166. concept invocable_dispatch = (NE && std::is_nothrow_invocable_r_v<
  167. R, D, Args...>) || (!NE && std::is_invocable_r_v<R, D, Args...>);
  168. template <class D, class P, qualifier_type Q, bool NE, class R, class... Args>
  169. concept invocable_dispatch_ptr_indirect = ptr_traits<P, Q, NE>::applicable &&
  170. invocable_dispatch<
  171. D, NE, R, typename ptr_traits<P, Q, NE>::target_type, Args...>;
  172. template <class D, class P, qualifier_type Q, bool NE, class R, class... Args>
  173. concept invocable_dispatch_ptr_direct = invocable_dispatch<
  174. D, NE, R, add_qualifier_t<P, Q>, Args...> && (Q != qualifier_type::rv ||
  175. (NE && std::is_nothrow_destructible_v<P>) ||
  176. (!NE && std::is_destructible_v<P>));
  177. template <bool NE, class R, class... Args>
  178. using func_ptr_t = std::conditional_t<
  179. NE, R (*)(Args...) noexcept, R (*)(Args...)>;
  180. template <class D, class R, class... Args>
  181. R invoke_dispatch(Args&&... args) {
  182. if constexpr (std::is_void_v<R>) {
  183. D{}(std::forward<Args>(args)...);
  184. } else {
  185. return D{}(std::forward<Args>(args)...);
  186. }
  187. }
  188. template <class D, class P, qualifier_type Q, class R, class... Args>
  189. R indirect_conv_dispatcher(add_qualifier_t<std::byte, Q> self, Args... args)
  190. noexcept(invocable_dispatch_ptr_indirect<D, P, Q, true, R, Args...>) {
  191. return invoke_dispatch<D, R>(*std::forward<add_qualifier_t<P, Q>>(
  192. *std::launder(reinterpret_cast<add_qualifier_ptr_t<P, Q>>(&self))),
  193. std::forward<Args>(args)...);
  194. }
  195. template <class D, class P, qualifier_type Q, class R, class... Args>
  196. R direct_conv_dispatcher(add_qualifier_t<std::byte, Q> self, Args... args)
  197. noexcept(invocable_dispatch_ptr_direct<D, P, Q, true, R, Args...>) {
  198. auto& qp = *std::launder(reinterpret_cast<add_qualifier_ptr_t<P, Q>>(&self));
  199. if constexpr (Q == qualifier_type::rv) {
  200. destruction_guard guard{&qp};
  201. return invoke_dispatch<D, R>(
  202. std::forward<add_qualifier_t<P, Q>>(qp), std::forward<Args>(args)...);
  203. } else {
  204. return invoke_dispatch<D, R>(
  205. std::forward<add_qualifier_t<P, Q>>(qp), std::forward<Args>(args)...);
  206. }
  207. }
  208. template <class D, qualifier_type Q, class R, class... Args>
  209. R default_conv_dispatcher(add_qualifier_t<std::byte, Q>, Args... args)
  210. noexcept(invocable_dispatch<D, true, R, std::nullptr_t, Args...>)
  211. { return invoke_dispatch<D, R>(nullptr, std::forward<Args>(args)...); }
  212. template <class P>
  213. void copying_dispatcher(std::byte& self, const std::byte& rhs)
  214. noexcept(has_copyability<P>(constraint_level::nothrow)) {
  215. std::construct_at(reinterpret_cast<P*>(&self),
  216. *std::launder(reinterpret_cast<const P*>(&rhs)));
  217. }
  218. template <std::size_t Len, std::size_t Align>
  219. void copying_default_dispatcher(std::byte& self, const std::byte& rhs)
  220. noexcept {
  221. std::uninitialized_copy_n(
  222. std::assume_aligned<Align>(&rhs), Len, std::assume_aligned<Align>(&self));
  223. }
  224. template <class P>
  225. void relocation_dispatcher(std::byte& self, const std::byte& rhs)
  226. noexcept(has_relocatability<P>(constraint_level::nothrow)) {
  227. P* other = std::launder(reinterpret_cast<P*>(const_cast<std::byte*>(&rhs)));
  228. destruction_guard guard{other};
  229. std::construct_at(reinterpret_cast<P*>(&self), std::move(*other));
  230. }
  231. template <class P>
  232. void destruction_dispatcher(std::byte& self)
  233. noexcept(has_destructibility<P>(constraint_level::nothrow))
  234. { std::destroy_at(std::launder(reinterpret_cast<P*>(&self))); }
  235. inline void destruction_default_dispatcher(std::byte&) noexcept {}
  236. template <class O> struct overload_traits : inapplicable_traits {};
  237. template <qualifier_type Q, bool NE, class R, class... Args>
  238. struct overload_traits_impl : applicable_traits {
  239. template <bool IsDirect, class D>
  240. struct meta_provider {
  241. template <class P>
  242. static constexpr auto get()
  243. -> func_ptr_t<NE, R, add_qualifier_t<std::byte, Q>, Args...> {
  244. if constexpr (!IsDirect &&
  245. invocable_dispatch_ptr_indirect<D, P, Q, NE, R, Args...>) {
  246. return &indirect_conv_dispatcher<D, P, Q, R, Args...>;
  247. } else if constexpr (IsDirect &&
  248. invocable_dispatch_ptr_direct<D, P, Q, NE, R, Args...>) {
  249. return &direct_conv_dispatcher<D, P, Q, R, Args...>;
  250. } else if constexpr (invocable_dispatch<
  251. D, NE, R, std::nullptr_t, Args...>) {
  252. return &default_conv_dispatcher<D, Q, R, Args...>;
  253. } else {
  254. return nullptr;
  255. }
  256. }
  257. };
  258. using return_type = R;
  259. using view_type = R(Args...) const noexcept(NE);
  260. template <bool IsDirect, class D, class P>
  261. static constexpr bool applicable_ptr =
  262. meta_provider<IsDirect, D>::template get<P>() != nullptr;
  263. static constexpr qualifier_type qualifier = Q;
  264. };
  265. template <class R, class... Args>
  266. struct overload_traits<R(Args...)>
  267. : overload_traits_impl<qualifier_type::lv, false, R, Args...> {};
  268. template <class R, class... Args>
  269. struct overload_traits<R(Args...) noexcept>
  270. : overload_traits_impl<qualifier_type::lv, true, R, Args...> {};
  271. template <class R, class... Args>
  272. struct overload_traits<R(Args...) &>
  273. : overload_traits_impl<qualifier_type::lv, false, R, Args...> {};
  274. template <class R, class... Args>
  275. struct overload_traits<R(Args...) & noexcept>
  276. : overload_traits_impl<qualifier_type::lv, true, R, Args...> {};
  277. template <class R, class... Args>
  278. struct overload_traits<R(Args...) &&>
  279. : overload_traits_impl<qualifier_type::rv, false, R, Args...> {};
  280. template <class R, class... Args>
  281. struct overload_traits<R(Args...) && noexcept>
  282. : overload_traits_impl<qualifier_type::rv, true, R, Args...> {};
  283. template <class R, class... Args>
  284. struct overload_traits<R(Args...) const>
  285. : overload_traits_impl<qualifier_type::const_lv, false, R, Args...> {};
  286. template <class R, class... Args>
  287. struct overload_traits<R(Args...) const noexcept>
  288. : overload_traits_impl<qualifier_type::const_lv, true, R, Args...> {};
  289. template <class R, class... Args>
  290. struct overload_traits<R(Args...) const&>
  291. : overload_traits_impl<qualifier_type::const_lv, false, R, Args...> {};
  292. template <class R, class... Args>
  293. struct overload_traits<R(Args...) const& noexcept>
  294. : overload_traits_impl<qualifier_type::const_lv, true, R, Args...> {};
  295. template <class R, class... Args>
  296. struct overload_traits<R(Args...) const&&>
  297. : overload_traits_impl<qualifier_type::const_rv, false, R, Args...> {};
  298. template <class R, class... Args>
  299. struct overload_traits<R(Args...) const&& noexcept>
  300. : overload_traits_impl<qualifier_type::const_rv, true, R, Args...> {};
  301. template <class MP>
  302. struct dispatcher_meta {
  303. constexpr dispatcher_meta() noexcept : dispatcher(nullptr) {}
  304. template <class P>
  305. constexpr explicit dispatcher_meta(std::in_place_type_t<P>) noexcept
  306. : dispatcher(MP::template get<P>()) {}
  307. decltype(MP::template get<void>()) dispatcher;
  308. };
  309. template <class... Ms>
  310. struct composite_meta_impl : Ms... {
  311. constexpr composite_meta_impl() noexcept = default;
  312. template <class P>
  313. constexpr explicit composite_meta_impl(std::in_place_type_t<P>) noexcept
  314. : Ms(std::in_place_type<P>)... {}
  315. };
  316. template <class O, class I> struct meta_reduction : std::type_identity<O> {};
  317. template <class... Ms, class I> requires(!std::is_void_v<I>)
  318. struct meta_reduction<composite_meta_impl<Ms...>, I>
  319. : std::type_identity<composite_meta_impl<Ms..., I>> {};
  320. template <class... Ms1, class... Ms2>
  321. struct meta_reduction<composite_meta_impl<Ms1...>, composite_meta_impl<Ms2...>>
  322. : std::type_identity<composite_meta_impl<Ms1..., Ms2...>> {};
  323. template <class O, class I>
  324. using meta_reduction_t = typename meta_reduction<O, I>::type;
  325. template <class... Ms>
  326. using composite_meta =
  327. recursive_reduction_t<meta_reduction_t, composite_meta_impl<>, Ms...>;
  328. template <class T>
  329. consteval bool is_is_direct_well_formed() {
  330. if constexpr (requires { { T::is_direct } -> std::same_as<const bool&>; }) {
  331. if constexpr (is_consteval([] { return T::is_direct; })) {
  332. return true;
  333. }
  334. }
  335. return false;
  336. }
  337. template <class C, class... Os>
  338. struct conv_traits_impl : inapplicable_traits {};
  339. template <class C, class... Os>
  340. requires(sizeof...(Os) > 0u && (overload_traits<Os>::applicable && ...))
  341. struct conv_traits_impl<C, Os...> : applicable_traits {
  342. using meta = composite_meta_impl<dispatcher_meta<typename overload_traits<Os>
  343. ::template meta_provider<C::is_direct, typename C::dispatch_type>>...>;
  344. template <class P>
  345. static constexpr bool applicable_ptr =
  346. (overload_traits<Os>::template applicable_ptr<
  347. C::is_direct, typename C::dispatch_type, P> && ...);
  348. };
  349. template <class C> struct conv_traits : inapplicable_traits {};
  350. template <class C>
  351. requires(
  352. requires {
  353. typename C::dispatch_type;
  354. typename C::overload_types;
  355. } &&
  356. is_is_direct_well_formed<C>() &&
  357. std::is_trivial_v<typename C::dispatch_type> &&
  358. is_tuple_like_well_formed<typename C::overload_types>())
  359. struct conv_traits<C>
  360. : instantiated_t<conv_traits_impl, typename C::overload_types, C> {};
  361. template <class P>
  362. using ptr_element_t = typename std::pointer_traits<P>::element_type;
  363. template <bool IsDirect, class R>
  364. struct refl_meta {
  365. template <class P> requires(IsDirect)
  366. constexpr explicit refl_meta(std::in_place_type_t<P>)
  367. : reflector(std::in_place_type<P>) {}
  368. template <class P> requires(!IsDirect)
  369. constexpr explicit refl_meta(std::in_place_type_t<P>)
  370. : reflector(std::in_place_type<ptr_element_t<P>>) {}
  371. R reflector;
  372. };
  373. template <class R, class T, bool IsDirect>
  374. consteval bool is_reflector_well_formed() {
  375. if constexpr (IsDirect) {
  376. if constexpr (std::is_constructible_v<R, std::in_place_type_t<T>>) {
  377. if constexpr (is_consteval([] { return R{std::in_place_type<T>}; })) {
  378. return true;
  379. }
  380. }
  381. } else if constexpr (requires { typename ptr_element_t<T>; }) {
  382. return is_reflector_well_formed<R, ptr_element_t<T>, true>();
  383. }
  384. return false;
  385. }
  386. template <class R> struct refl_traits : inapplicable_traits {};
  387. template <class R>
  388. requires(requires { typename R::reflector_type; } &&
  389. is_is_direct_well_formed<R>())
  390. struct refl_traits<R> : applicable_traits {
  391. using meta = refl_meta<R::is_direct, typename R::reflector_type>;
  392. template <class P>
  393. static constexpr bool applicable_ptr =
  394. is_reflector_well_formed<typename R::reflector_type, P, R::is_direct>();
  395. };
  396. template <bool NE>
  397. struct copyability_meta_provider {
  398. template <class P>
  399. static constexpr func_ptr_t<NE, void, std::byte&, const std::byte&> get() {
  400. if constexpr (has_copyability<P>(constraint_level::trivial)) {
  401. return &copying_default_dispatcher<sizeof(P), alignof(P)>;
  402. } else {
  403. return &copying_dispatcher<P>;
  404. }
  405. }
  406. };
  407. template <bool NE>
  408. struct relocatability_meta_provider {
  409. template <class P>
  410. static constexpr func_ptr_t<NE, void, std::byte&, const std::byte&> get() {
  411. if constexpr (has_relocatability<P>(constraint_level::trivial)) {
  412. return &copying_default_dispatcher<sizeof(P), alignof(P)>;
  413. } else {
  414. return &relocation_dispatcher<P>;
  415. }
  416. }
  417. };
  418. template <bool NE>
  419. struct destructibility_meta_provider {
  420. template <class P>
  421. static constexpr func_ptr_t<NE, void, std::byte&> get() {
  422. if constexpr (has_destructibility<P>(constraint_level::trivial)) {
  423. return &destruction_default_dispatcher;
  424. } else {
  425. return &destruction_dispatcher<P>;
  426. }
  427. }
  428. };
  429. template <template <bool> class MP, constraint_level C>
  430. struct lifetime_meta_traits : std::type_identity<void> {};
  431. template <template <bool> class MP>
  432. struct lifetime_meta_traits<MP, constraint_level::nothrow>
  433. : std::type_identity<dispatcher_meta<MP<true>>> {};
  434. template <template <bool> class MP>
  435. struct lifetime_meta_traits<MP, constraint_level::nontrivial>
  436. : std::type_identity<dispatcher_meta<MP<false>>> {};
  437. template <template <bool> class MP, constraint_level C>
  438. using lifetime_meta_t = typename lifetime_meta_traits<MP, C>::type;
  439. template <class... As>
  440. class ___PRO_ENFORCE_EBO composite_accessor_impl : public As... {
  441. template <class> friend class pro::proxy;
  442. template <class F> friend struct pro::proxy_indirect_accessor;
  443. composite_accessor_impl() noexcept = default;
  444. composite_accessor_impl(const composite_accessor_impl&) noexcept = default;
  445. composite_accessor_impl& operator=(const composite_accessor_impl&) noexcept
  446. = default;
  447. };
  448. template <class T>
  449. struct accessor_traits_impl : std::type_identity<void> {};
  450. template <class T>
  451. requires(std::is_nothrow_default_constructible_v<T> &&
  452. std::is_trivially_copyable_v<T> && !std::is_final_v<T>)
  453. struct accessor_traits_impl<T> : std::type_identity<T> {};
  454. template <class SFINAE, class T, class F>
  455. struct accessor_traits : std::type_identity<void> {};
  456. template <class T, class F>
  457. struct accessor_traits<std::void_t<typename T::template accessor<F>>, T, F>
  458. : accessor_traits_impl<typename T::template accessor<F>> {};
  459. template <class T, class F>
  460. using accessor_t = typename accessor_traits<void, T, F>::type;
  461. template <bool IsDirect, class F, class O, class I>
  462. struct composite_accessor_reduction : std::type_identity<O> {};
  463. template <bool IsDirect, class F, class... As, class I>
  464. requires(IsDirect == I::is_direct && !std::is_void_v<accessor_t<I, F>>)
  465. struct composite_accessor_reduction<
  466. IsDirect, F, composite_accessor_impl<As...>, I>
  467. : std::type_identity<composite_accessor_impl<As..., accessor_t<I, F>>> {};
  468. template <bool IsDirect, class F>
  469. struct composite_accessor_helper {
  470. template <class O, class I>
  471. using reduction_t =
  472. typename composite_accessor_reduction<IsDirect, F, O, I>::type;
  473. };
  474. template <bool IsDirect, class F, class... Ts>
  475. using composite_accessor = recursive_reduction_t<
  476. composite_accessor_helper<IsDirect, F>::template reduction_t,
  477. composite_accessor_impl<>, Ts...>;
  478. template <class A1, class A2> struct composite_accessor_merge_traits;
  479. template <class... A1, class... A2>
  480. struct composite_accessor_merge_traits<
  481. composite_accessor_impl<A1...>, composite_accessor_impl<A2...>>
  482. : std::type_identity<composite_accessor_impl<A1..., A2...>> {};
  483. template <class A1, class A2>
  484. using merged_composite_accessor =
  485. typename composite_accessor_merge_traits<A1, A2>::type;
  486. template <class T> struct in_place_type_traits : inapplicable_traits {};
  487. template <class T>
  488. struct in_place_type_traits<std::in_place_type_t<T>> : applicable_traits {};
  489. template <class T>
  490. constexpr bool is_in_place_type = in_place_type_traits<T>::applicable;
  491. template <class F>
  492. consteval bool is_facade_constraints_well_formed() {
  493. if constexpr (requires {
  494. { F::constraints } -> std::same_as<const proxiable_ptr_constraints&>; }) {
  495. if constexpr (is_consteval([] { return F::constraints; })) {
  496. return std::has_single_bit(F::constraints.max_align) &&
  497. F::constraints.max_size % F::constraints.max_align == 0u;
  498. }
  499. }
  500. return false;
  501. }
  502. template <class F, class... Cs>
  503. struct facade_conv_traits_impl : inapplicable_traits {};
  504. template <class F, class... Cs> requires(conv_traits<Cs>::applicable && ...)
  505. struct facade_conv_traits_impl<F, Cs...> : applicable_traits {
  506. using conv_meta = composite_meta<typename conv_traits<Cs>::meta...>;
  507. using conv_indirect_accessor = composite_accessor<false, F, Cs...>;
  508. using conv_direct_accessor = composite_accessor<true, F, Cs...>;
  509. template <class P>
  510. static constexpr bool conv_applicable_ptr =
  511. (conv_traits<Cs>::template applicable_ptr<P> && ...);
  512. template <bool IsDirect, class D, class O>
  513. static constexpr bool is_invocable = std::is_base_of_v<dispatcher_meta<
  514. typename overload_traits<O>::template meta_provider<IsDirect, D>>,
  515. conv_meta>;
  516. };
  517. template <class F, class... Rs>
  518. struct facade_refl_traits_impl : inapplicable_traits {};
  519. template <class F, class... Rs> requires(refl_traits<Rs>::applicable && ...)
  520. struct facade_refl_traits_impl<F, Rs...> : applicable_traits {
  521. using refl_meta = composite_meta<typename refl_traits<Rs>::meta...>;
  522. using refl_indirect_accessor = composite_accessor<false, F, Rs...>;
  523. using refl_direct_accessor = composite_accessor<true, F, Rs...>;
  524. template <class P>
  525. static constexpr bool refl_applicable_ptr =
  526. (refl_traits<Rs>::template applicable_ptr<P> && ...);
  527. };
  528. template <class F> struct facade_traits : inapplicable_traits {};
  529. template <class F>
  530. requires(
  531. requires {
  532. typename F::convention_types;
  533. typename F::reflection_types;
  534. } &&
  535. is_facade_constraints_well_formed<F>() &&
  536. is_tuple_like_well_formed<typename F::convention_types>() &&
  537. instantiated_t<facade_conv_traits_impl, typename F::convention_types, F>
  538. ::applicable &&
  539. is_tuple_like_well_formed<typename F::reflection_types>() &&
  540. instantiated_t<facade_refl_traits_impl, typename F::reflection_types, F>
  541. ::applicable)
  542. struct facade_traits<F>
  543. : instantiated_t<facade_conv_traits_impl, typename F::convention_types, F>,
  544. instantiated_t<facade_refl_traits_impl, typename F::reflection_types, F> {
  545. using copyability_meta = lifetime_meta_t<
  546. copyability_meta_provider, F::constraints.copyability>;
  547. using relocatability_meta = lifetime_meta_t<
  548. relocatability_meta_provider,
  549. F::constraints.copyability == constraint_level::trivial ?
  550. constraint_level::trivial : F::constraints.relocatability>;
  551. using destructibility_meta = lifetime_meta_t<
  552. destructibility_meta_provider, F::constraints.destructibility>;
  553. using meta = composite_meta<copyability_meta, relocatability_meta,
  554. destructibility_meta, typename facade_traits::conv_meta,
  555. typename facade_traits::refl_meta>;
  556. using indirect_accessor = merged_composite_accessor<
  557. typename facade_traits::conv_indirect_accessor,
  558. typename facade_traits::refl_indirect_accessor>;
  559. using direct_accessor = merged_composite_accessor<
  560. typename facade_traits::conv_direct_accessor,
  561. typename facade_traits::refl_direct_accessor>;
  562. };
  563. using ptr_prototype = void*[2];
  564. template <class M>
  565. struct meta_ptr_indirect_impl {
  566. constexpr meta_ptr_indirect_impl() noexcept : ptr_(nullptr) {};
  567. template <class P>
  568. constexpr explicit meta_ptr_indirect_impl(std::in_place_type_t<P>) noexcept
  569. : ptr_(&storage<P>) {}
  570. bool has_value() const noexcept { return ptr_ != nullptr; }
  571. void reset() noexcept { ptr_ = nullptr; }
  572. const M* operator->() const noexcept { return ptr_; }
  573. private:
  574. const M* ptr_;
  575. template <class P> static constexpr M storage{std::in_place_type<P>};
  576. };
  577. template <class M, class DM>
  578. struct meta_ptr_direct_impl : private M {
  579. using M::M;
  580. bool has_value() const noexcept { return this->DM::dispatcher != nullptr; }
  581. void reset() noexcept { this->DM::dispatcher = nullptr; }
  582. const M* operator->() const noexcept { return this; }
  583. };
  584. template <class M>
  585. struct meta_ptr_traits_impl : std::type_identity<meta_ptr_indirect_impl<M>> {};
  586. template <class MP, class... Ms>
  587. struct meta_ptr_traits_impl<composite_meta_impl<dispatcher_meta<MP>, Ms...>>
  588. : std::type_identity<meta_ptr_direct_impl<composite_meta_impl<
  589. dispatcher_meta<MP>, Ms...>, dispatcher_meta<MP>>> {};
  590. template <class M>
  591. struct meta_ptr_traits : std::type_identity<meta_ptr_indirect_impl<M>> {};
  592. template <class M>
  593. requires(sizeof(M) <= sizeof(ptr_prototype) &&
  594. alignof(M) <= alignof(ptr_prototype) &&
  595. std::is_nothrow_default_constructible_v<M> &&
  596. std::is_trivially_copyable_v<M>)
  597. struct meta_ptr_traits<M> : meta_ptr_traits_impl<M> {};
  598. template <class M>
  599. using meta_ptr = typename meta_ptr_traits<M>::type;
  600. template <class MP>
  601. struct meta_ptr_reset_guard {
  602. public:
  603. explicit meta_ptr_reset_guard(MP& meta) noexcept : meta_(meta) {}
  604. meta_ptr_reset_guard(const meta_ptr_reset_guard&) = delete;
  605. ~meta_ptr_reset_guard() { meta_.reset(); }
  606. private:
  607. MP& meta_;
  608. };
  609. template <class F>
  610. struct proxy_helper {
  611. static inline const auto& get_meta(const proxy<F>& p) noexcept {
  612. assert(p.has_value());
  613. return *p.meta_.operator->();
  614. }
  615. template <bool IsDirect, class D, class O, qualifier_type Q, class... Args>
  616. static decltype(auto) invoke(add_qualifier_t<proxy<F>, Q> p, Args&&... args) {
  617. auto dispatcher = get_meta(p)
  618. .template dispatcher_meta<typename overload_traits<O>
  619. ::template meta_provider<IsDirect, D>>::dispatcher;
  620. if constexpr (
  621. IsDirect && overload_traits<O>::qualifier == qualifier_type::rv) {
  622. meta_ptr_reset_guard guard{p.meta_};
  623. return dispatcher(std::forward<add_qualifier_t<std::byte, Q>>(*p.ptr_),
  624. std::forward<Args>(args)...);
  625. } else {
  626. return dispatcher(std::forward<add_qualifier_t<std::byte, Q>>(*p.ptr_),
  627. std::forward<Args>(args)...);
  628. }
  629. }
  630. template <class A, qualifier_type Q>
  631. static add_qualifier_t<proxy<F>, Q> access(add_qualifier_t<A, Q> a) {
  632. if constexpr (std::is_base_of_v<A, proxy<F>>) {
  633. return static_cast<add_qualifier_t<proxy<F>, Q>>(
  634. std::forward<add_qualifier_t<A, Q>>(a));
  635. } else {
  636. // Note: The use of offsetof below is technically undefined until C++20
  637. // because proxy may not be a standard layout type. However, all compilers
  638. // currently provide well-defined behavior as an extension (which is
  639. // demonstrated since constexpr evaluation must diagnose all undefined
  640. // behavior). However, various compilers also warn about this use of
  641. // offsetof, which must be suppressed.
  642. #if defined(__INTEL_COMPILER)
  643. #pragma warning push
  644. #pragma warning(disable : 1875)
  645. #elif defined(__GNUC__) || defined(__clang__)
  646. #pragma GCC diagnostic push
  647. #pragma GCC diagnostic ignored "-Winvalid-offsetof"
  648. #endif // defined(__INTEL_COMPILER)
  649. #if defined(__NVCC__)
  650. #pragma nv_diagnostic push
  651. #pragma nv_diag_suppress 1427
  652. #endif // defined(__NVCC__)
  653. #if defined(__NVCOMPILER)
  654. #pragma diagnostic push
  655. #pragma diag_suppress offset_in_non_POD_nonstandard
  656. #endif // defined(__NVCOMPILER)
  657. constexpr std::size_t offset = offsetof(proxy<F>, ia_);
  658. #if defined(__INTEL_COMPILER)
  659. #pragma warning pop
  660. #elif defined(__GNUC__) || defined(__clang__)
  661. #pragma GCC diagnostic pop
  662. #endif // defined(__INTEL_COMPILER)
  663. #if defined(__NVCC__)
  664. #pragma nv_diagnostic pop
  665. #endif // defined(__NVCC__)
  666. #if defined(__NVCOMPILER)
  667. #pragma diagnostic pop
  668. #endif // defined(__NVCOMPILER)
  669. return reinterpret_cast<add_qualifier_t<proxy<F>, Q>>(*(reinterpret_cast<
  670. add_qualifier_ptr_t<std::byte, Q>>(static_cast<add_qualifier_ptr_t<
  671. proxy_indirect_accessor<F>, Q>>(std::addressof(a))) - offset));
  672. }
  673. }
  674. };
  675. } // namespace details
  676. template <class F>
  677. concept facade = details::facade_traits<F>::applicable;
  678. template <class P, class F>
  679. concept proxiable = facade<F> && sizeof(P) <= F::constraints.max_size &&
  680. alignof(P) <= F::constraints.max_align &&
  681. details::has_copyability<P>(F::constraints.copyability) &&
  682. details::has_relocatability<P>(F::constraints.relocatability) &&
  683. details::has_destructibility<P>(F::constraints.destructibility) &&
  684. details::facade_traits<F>::template conv_applicable_ptr<P> &&
  685. details::facade_traits<F>::template refl_applicable_ptr<P>;
  686. template <class F> struct proxy_indirect_accessor {};
  687. template <class F> requires(!std::is_same_v<typename details::facade_traits<F>
  688. ::indirect_accessor, details::composite_accessor_impl<>>)
  689. struct proxy_indirect_accessor<F>
  690. : details::facade_traits<F>::indirect_accessor {};
  691. template <class F>
  692. class proxy : public details::facade_traits<F>::direct_accessor {
  693. static_assert(facade<F>);
  694. friend struct details::proxy_helper<F>;
  695. using _Traits = details::facade_traits<F>;
  696. public:
  697. proxy() noexcept {
  698. ___PRO_DEBUG(
  699. std::ignore = static_cast<proxy_indirect_accessor<F>*
  700. (proxy::*)() noexcept>(&proxy::operator->);
  701. std::ignore = static_cast<const proxy_indirect_accessor<F>*
  702. (proxy::*)() const noexcept>(&proxy::operator->);
  703. std::ignore = static_cast<proxy_indirect_accessor<F>&
  704. (proxy::*)() & noexcept>(&proxy::operator*);
  705. std::ignore = static_cast<const proxy_indirect_accessor<F>&
  706. (proxy::*)() const& noexcept>(&proxy::operator*);
  707. std::ignore = static_cast<proxy_indirect_accessor<F>&&
  708. (proxy::*)() && noexcept>(&proxy::operator*);
  709. std::ignore = static_cast<const proxy_indirect_accessor<F>&&
  710. (proxy::*)() const&& noexcept>(&proxy::operator*);
  711. )
  712. }
  713. proxy(std::nullptr_t) noexcept : proxy() {}
  714. proxy(const proxy&) noexcept requires(F::constraints.copyability ==
  715. constraint_level::trivial) = default;
  716. proxy(const proxy& rhs)
  717. noexcept(F::constraints.copyability == constraint_level::nothrow)
  718. requires(F::constraints.copyability == constraint_level::nontrivial ||
  719. F::constraints.copyability == constraint_level::nothrow) {
  720. if (rhs.meta_.has_value()) {
  721. rhs.meta_->_Traits::copyability_meta::dispatcher(*ptr_, *rhs.ptr_);
  722. meta_ = rhs.meta_;
  723. }
  724. }
  725. proxy(proxy&& rhs)
  726. noexcept(F::constraints.relocatability == constraint_level::nothrow)
  727. requires(F::constraints.relocatability >= constraint_level::nontrivial &&
  728. F::constraints.copyability != constraint_level::trivial) {
  729. if (rhs.meta_.has_value()) {
  730. details::meta_ptr_reset_guard guard{rhs.meta_};
  731. if constexpr (F::constraints.relocatability ==
  732. constraint_level::trivial) {
  733. std::ranges::uninitialized_copy(rhs.ptr_, ptr_);
  734. } else {
  735. rhs.meta_->_Traits::relocatability_meta::dispatcher(*ptr_, *rhs.ptr_);
  736. }
  737. meta_ = rhs.meta_;
  738. }
  739. }
  740. template <class P>
  741. proxy(P&& ptr) noexcept(std::is_nothrow_constructible_v<std::decay_t<P>, P>)
  742. requires(!details::is_in_place_type<std::decay_t<P>> &&
  743. proxiable<std::decay_t<P>, F> &&
  744. std::is_constructible_v<std::decay_t<P>, P>)
  745. : proxy() { initialize<std::decay_t<P>>(std::forward<P>(ptr)); }
  746. template <proxiable<F> P, class... Args>
  747. explicit proxy(std::in_place_type_t<P>, Args&&... args)
  748. noexcept(std::is_nothrow_constructible_v<P, Args...>)
  749. requires(std::is_constructible_v<P, Args...>)
  750. : proxy() { initialize<P>(std::forward<Args>(args)...); }
  751. template <proxiable<F> P, class U, class... Args>
  752. explicit proxy(std::in_place_type_t<P>, std::initializer_list<U> il,
  753. Args&&... args)
  754. noexcept(std::is_nothrow_constructible_v<
  755. P, std::initializer_list<U>&, Args...>)
  756. requires(std::is_constructible_v<P, std::initializer_list<U>&, Args...>)
  757. : proxy() { initialize<P>(il, std::forward<Args>(args)...); }
  758. proxy& operator=(std::nullptr_t)
  759. noexcept(F::constraints.destructibility >= constraint_level::nothrow)
  760. requires(F::constraints.destructibility >= constraint_level::nontrivial)
  761. { reset(); return *this; }
  762. proxy& operator=(const proxy&) noexcept requires(F::constraints.copyability ==
  763. constraint_level::trivial) = default;
  764. proxy& operator=(const proxy& rhs)
  765. noexcept(F::constraints.copyability >= constraint_level::nothrow &&
  766. F::constraints.destructibility >= constraint_level::nothrow)
  767. requires((F::constraints.copyability == constraint_level::nontrivial ||
  768. F::constraints.copyability == constraint_level::nothrow) &&
  769. F::constraints.destructibility >= constraint_level::nontrivial) {
  770. if (this != &rhs) {
  771. if constexpr (F::constraints.copyability == constraint_level::nothrow) {
  772. std::destroy_at(this);
  773. std::construct_at(this, rhs);
  774. } else {
  775. *this = proxy{rhs};
  776. }
  777. }
  778. return *this;
  779. }
  780. proxy& operator=(proxy&& rhs)
  781. noexcept(F::constraints.relocatability >= constraint_level::nothrow &&
  782. F::constraints.destructibility >= constraint_level::nothrow)
  783. requires(F::constraints.relocatability >= constraint_level::nontrivial &&
  784. F::constraints.destructibility >= constraint_level::nontrivial &&
  785. F::constraints.copyability != constraint_level::trivial) {
  786. if (this != &rhs) {
  787. reset();
  788. std::construct_at(this, std::move(rhs));
  789. }
  790. return *this;
  791. }
  792. template <class P>
  793. proxy& operator=(P&& ptr)
  794. noexcept(std::is_nothrow_constructible_v<std::decay_t<P>, P> &&
  795. F::constraints.destructibility >= constraint_level::nothrow)
  796. requires(proxiable<std::decay_t<P>, F> &&
  797. std::is_constructible_v<std::decay_t<P>, P> &&
  798. F::constraints.destructibility >= constraint_level::nontrivial) {
  799. if constexpr (std::is_nothrow_constructible_v<std::decay_t<P>, P>) {
  800. std::destroy_at(this);
  801. initialize<std::decay_t<P>>(std::forward<P>(ptr));
  802. } else {
  803. *this = proxy{std::forward<P>(ptr)};
  804. }
  805. return *this;
  806. }
  807. ~proxy() requires(F::constraints.destructibility == constraint_level::trivial)
  808. = default;
  809. ~proxy() noexcept(F::constraints.destructibility == constraint_level::nothrow)
  810. requires(F::constraints.destructibility == constraint_level::nontrivial ||
  811. F::constraints.destructibility == constraint_level::nothrow) {
  812. if (meta_.has_value())
  813. { meta_->_Traits::destructibility_meta::dispatcher(*ptr_); }
  814. }
  815. bool has_value() const noexcept { return meta_.has_value(); }
  816. explicit operator bool() const noexcept { return meta_.has_value(); }
  817. void reset()
  818. noexcept(F::constraints.destructibility >= constraint_level::nothrow)
  819. requires(F::constraints.destructibility >= constraint_level::nontrivial)
  820. { std::destroy_at(this); meta_.reset(); }
  821. void swap(proxy& rhs)
  822. noexcept(F::constraints.relocatability >= constraint_level::nothrow ||
  823. F::constraints.copyability == constraint_level::trivial)
  824. requires(F::constraints.relocatability >= constraint_level::nontrivial ||
  825. F::constraints.copyability == constraint_level::trivial) {
  826. if constexpr (F::constraints.relocatability == constraint_level::trivial ||
  827. F::constraints.copyability == constraint_level::trivial) {
  828. std::swap(meta_, rhs.meta_);
  829. std::swap(ptr_, rhs.ptr);
  830. } else {
  831. if (meta_.has_value()) {
  832. if (rhs.meta_.has_value()) {
  833. proxy temp = std::move(*this);
  834. std::construct_at(this, std::move(rhs));
  835. std::construct_at(&rhs, std::move(temp));
  836. } else {
  837. std::construct_at(&rhs, std::move(*this));
  838. }
  839. } else if (rhs.meta_.has_value()) {
  840. std::construct_at(this, std::move(rhs));
  841. }
  842. }
  843. }
  844. template <proxiable<F> P, class... Args>
  845. P& emplace(Args&&... args)
  846. noexcept(std::is_nothrow_constructible_v<P, Args...> &&
  847. F::constraints.destructibility >= constraint_level::nothrow)
  848. requires(std::is_constructible_v<P, Args...> &&
  849. F::constraints.destructibility >= constraint_level::nontrivial)
  850. { reset(); return initialize<P>(std::forward<Args>(args)...); }
  851. template <proxiable<F> P, class U, class... Args>
  852. P& emplace(std::initializer_list<U> il, Args&&... args)
  853. noexcept(std::is_nothrow_constructible_v<
  854. P, std::initializer_list<U>&, Args...> &&
  855. F::constraints.destructibility >= constraint_level::nothrow)
  856. requires(std::is_constructible_v<P, std::initializer_list<U>&, Args...> &&
  857. F::constraints.destructibility >= constraint_level::nontrivial)
  858. { reset(); return initialize<P>(il, std::forward<Args>(args)...); }
  859. proxy_indirect_accessor<F>* operator->() noexcept
  860. { return std::addressof(ia_); }
  861. const proxy_indirect_accessor<F>* operator->() const noexcept
  862. { return std::addressof(ia_); }
  863. proxy_indirect_accessor<F>& operator*() & noexcept { return ia_; }
  864. const proxy_indirect_accessor<F>& operator*() const& noexcept { return ia_; }
  865. proxy_indirect_accessor<F>&& operator*() && noexcept
  866. { return std::move(ia_); }
  867. const proxy_indirect_accessor<F>&& operator*() const&& noexcept
  868. { return std::move(ia_); }
  869. friend void swap(proxy& lhs, proxy& rhs) noexcept(noexcept(lhs.swap(rhs)))
  870. { lhs.swap(rhs); }
  871. friend bool operator==(const proxy& lhs, std::nullptr_t) noexcept
  872. { return !lhs.has_value(); }
  873. private:
  874. template <class P, class... Args>
  875. P& initialize(Args&&... args) {
  876. P& result = *std::construct_at(
  877. reinterpret_cast<P*>(ptr_), std::forward<Args>(args)...);
  878. if constexpr (std::is_constructible_v<bool, P&>) { assert(result); }
  879. meta_ = details::meta_ptr<typename _Traits::meta>{std::in_place_type<P>};
  880. return result;
  881. }
  882. [[___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE]]
  883. proxy_indirect_accessor<F> ia_;
  884. details::meta_ptr<typename _Traits::meta> meta_;
  885. alignas(F::constraints.max_align) std::byte ptr_[F::constraints.max_size];
  886. };
  887. template <bool IsDirect, class D, class O, class F, class... Args>
  888. auto proxy_invoke(proxy<F>& p, Args&&... args)
  889. -> typename details::overload_traits<O>::return_type {
  890. return details::proxy_helper<F>::template invoke<IsDirect, D, O,
  891. details::qualifier_type::lv>(p, std::forward<Args>(args)...);
  892. }
  893. template <bool IsDirect, class D, class O, class F, class... Args>
  894. auto proxy_invoke(const proxy<F>& p, Args&&... args)
  895. -> typename details::overload_traits<O>::return_type {
  896. return details::proxy_helper<F>::template invoke<IsDirect, D, O,
  897. details::qualifier_type::const_lv>(p, std::forward<Args>(args)...);
  898. }
  899. template <bool IsDirect, class D, class O, class F, class... Args>
  900. auto proxy_invoke(proxy<F>&& p, Args&&... args)
  901. -> typename details::overload_traits<O>::return_type {
  902. return details::proxy_helper<F>::template invoke<
  903. IsDirect, D, O, details::qualifier_type::rv>(
  904. std::move(p), std::forward<Args>(args)...);
  905. }
  906. template <bool IsDirect, class D, class O, class F, class... Args>
  907. auto proxy_invoke(const proxy<F>&& p, Args&&... args)
  908. -> typename details::overload_traits<O>::return_type {
  909. return details::proxy_helper<F>::template invoke<
  910. IsDirect, D, O, details::qualifier_type::const_rv>(
  911. std::move(p), std::forward<Args>(args)...);
  912. }
  913. template <bool IsDirect, class R, class F>
  914. const R& proxy_reflect(const proxy<F>& p) noexcept {
  915. return static_cast<const details::refl_meta<IsDirect, R>&>(
  916. details::proxy_helper<F>::get_meta(p)).reflector;
  917. }
  918. template <class F, class A>
  919. proxy<F>& access_proxy(A& a) noexcept {
  920. return details::proxy_helper<F>::template access<
  921. A, details::qualifier_type::lv>(a);
  922. }
  923. template <class F, class A>
  924. const proxy<F>& access_proxy(const A& a) noexcept {
  925. return details::proxy_helper<F>::template access<
  926. A, details::qualifier_type::const_lv>(a);
  927. }
  928. template <class F, class A>
  929. proxy<F>&& access_proxy(A&& a) noexcept {
  930. return details::proxy_helper<F>::template access<
  931. A, details::qualifier_type::rv>(std::forward<A>(a));
  932. }
  933. template <class F, class A>
  934. const proxy<F>&& access_proxy(const A&& a) noexcept {
  935. return details::proxy_helper<F>::template access<
  936. A, details::qualifier_type::const_rv>(std::forward<const A>(a));
  937. }
  938. namespace details {
  939. template <class T>
  940. class inplace_ptr {
  941. public:
  942. template <class... Args>
  943. inplace_ptr(Args&&... args)
  944. noexcept(std::is_nothrow_constructible_v<T, Args...>)
  945. requires(std::is_constructible_v<T, Args...>)
  946. : value_(std::forward<Args>(args)...) {}
  947. inplace_ptr(const inplace_ptr&)
  948. noexcept(std::is_nothrow_copy_constructible_v<T>) = default;
  949. inplace_ptr(inplace_ptr&&)
  950. noexcept(std::is_nothrow_move_constructible_v<T>) = default;
  951. T* operator->() noexcept { return &value_; }
  952. const T* operator->() const noexcept { return &value_; }
  953. T& operator*() & noexcept { return value_; }
  954. const T& operator*() const& noexcept { return value_; }
  955. T&& operator*() && noexcept { return std::forward<T>(value_); }
  956. const T&& operator*() const&& noexcept
  957. { return std::forward<const T>(value_); }
  958. private:
  959. T value_;
  960. };
  961. #if __STDC_HOSTED__
  962. template <class T, class Alloc>
  963. static auto rebind_allocator(const Alloc& alloc) {
  964. return typename std::allocator_traits<Alloc>::template rebind_alloc<T>(alloc);
  965. }
  966. template <class T, class Alloc, class... Args>
  967. static T* allocate(const Alloc& alloc, Args&&... args) {
  968. auto al = rebind_allocator<T>(alloc);
  969. auto deleter = [&](T* ptr) { al.deallocate(ptr, 1); };
  970. std::unique_ptr<T, decltype(deleter)> result{al.allocate(1), deleter};
  971. std::construct_at(result.get(), std::forward<Args>(args)...);
  972. return result.release();
  973. }
  974. template <class Alloc, class T>
  975. static void deallocate(const Alloc& alloc, T* ptr) {
  976. auto al = rebind_allocator<T>(alloc);
  977. std::destroy_at(ptr);
  978. al.deallocate(ptr, 1);
  979. }
  980. template <class T, class Alloc>
  981. class allocated_ptr {
  982. public:
  983. template <class... Args>
  984. allocated_ptr(const Alloc& alloc, Args&&... args)
  985. requires(std::is_constructible_v<T, Args...>)
  986. : alloc_(alloc), ptr_(allocate<T>(alloc, std::forward<Args>(args)...)) {}
  987. allocated_ptr(const allocated_ptr& rhs)
  988. requires(std::is_copy_constructible_v<T>)
  989. : alloc_(rhs.alloc_), ptr_(rhs.ptr_ == nullptr ? nullptr :
  990. allocate<T>(alloc_, std::as_const(*rhs.ptr_))) {}
  991. allocated_ptr(allocated_ptr&& rhs)
  992. noexcept(std::is_nothrow_move_constructible_v<Alloc>)
  993. : alloc_(std::move(rhs.alloc_)), ptr_(std::exchange(rhs.ptr_, nullptr)) {}
  994. ~allocated_ptr() { if (ptr_ != nullptr) { deallocate(alloc_, ptr_); } }
  995. T* operator->() noexcept { return ptr_; }
  996. const T* operator->() const noexcept { return ptr_; }
  997. T& operator*() & noexcept { return *ptr_; }
  998. const T& operator*() const& noexcept { return *ptr_; }
  999. T&& operator*() && noexcept { return std::forward<T>(*ptr_); }
  1000. const T&& operator*() const&& noexcept
  1001. { return std::forward<const T>(*ptr_); }
  1002. private:
  1003. [[___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE]]
  1004. Alloc alloc_;
  1005. T* ptr_;
  1006. };
  1007. template <class T, class Alloc>
  1008. class compact_ptr {
  1009. public:
  1010. template <class... Args>
  1011. compact_ptr(const Alloc& alloc, Args&&... args)
  1012. requires(std::is_constructible_v<T, Args...>)
  1013. : ptr_(allocate<storage>(alloc, alloc, std::forward<Args>(args)...)) {}
  1014. compact_ptr(const compact_ptr& rhs) requires(std::is_copy_constructible_v<T>)
  1015. : ptr_(rhs.ptr_ == nullptr ? nullptr : allocate<storage>(rhs.ptr_->alloc,
  1016. rhs.ptr_->alloc, std::as_const(rhs.ptr_->value))) {}
  1017. compact_ptr(compact_ptr&& rhs) noexcept
  1018. : ptr_(std::exchange(rhs.ptr_, nullptr)) {}
  1019. ~compact_ptr() { if (ptr_ != nullptr) { deallocate(ptr_->alloc, ptr_); } }
  1020. T* operator->() noexcept { return &ptr_->value; }
  1021. const T* operator->() const noexcept { return &ptr_->value; }
  1022. T& operator*() & noexcept { return ptr_->value; }
  1023. const T& operator*() const& noexcept { return ptr_->value; }
  1024. T&& operator*() && noexcept { return std::forward<T>(ptr_->value); }
  1025. const T&& operator*() const&& noexcept
  1026. { return std::forward<const T>(ptr_->value); }
  1027. private:
  1028. struct storage {
  1029. template <class... Args>
  1030. explicit storage(const Alloc& alloc, Args&&... args)
  1031. : value(std::forward<Args>(args)...), alloc(alloc) {}
  1032. T value;
  1033. Alloc alloc;
  1034. };
  1035. storage* ptr_;
  1036. };
  1037. template <class F, class T, class Alloc, class... Args>
  1038. proxy<F> allocate_proxy_impl(const Alloc& alloc, Args&&... args) {
  1039. if constexpr (proxiable<allocated_ptr<T, Alloc>, F>) {
  1040. return proxy<F>{std::in_place_type<allocated_ptr<T, Alloc>>,
  1041. alloc, std::forward<Args>(args)...};
  1042. } else {
  1043. return proxy<F>{std::in_place_type<compact_ptr<T, Alloc>>,
  1044. alloc, std::forward<Args>(args)...};
  1045. }
  1046. }
  1047. template <class F, class T, class... Args>
  1048. proxy<F> make_proxy_impl(Args&&... args) {
  1049. if constexpr (proxiable<inplace_ptr<T>, F>) {
  1050. return proxy<F>{std::in_place_type<inplace_ptr<T>>,
  1051. std::forward<Args>(args)...};
  1052. } else {
  1053. return allocate_proxy_impl<F, T>(
  1054. std::allocator<T>{}, std::forward<Args>(args)...);
  1055. }
  1056. }
  1057. #endif // __STDC_HOSTED__
  1058. } // namespace details
  1059. template <class T, class F>
  1060. concept inplace_proxiable_target = proxiable<details::inplace_ptr<T>, F>;
  1061. template <facade F, inplace_proxiable_target<F> T, class... Args>
  1062. proxy<F> make_proxy_inplace(Args&&... args)
  1063. noexcept(std::is_nothrow_constructible_v<T, Args...>) {
  1064. return proxy<F>{std::in_place_type<details::inplace_ptr<T>>,
  1065. std::forward<Args>(args)...};
  1066. }
  1067. template <facade F, inplace_proxiable_target<F> T, class U, class... Args>
  1068. proxy<F> make_proxy_inplace(std::initializer_list<U> il, Args&&... args)
  1069. noexcept(std::is_nothrow_constructible_v<
  1070. T, std::initializer_list<U>&, Args...>) {
  1071. return proxy<F>{std::in_place_type<details::inplace_ptr<T>>,
  1072. il, std::forward<Args>(args)...};
  1073. }
  1074. template <facade F, class T>
  1075. proxy<F> make_proxy_inplace(T&& value)
  1076. noexcept(std::is_nothrow_constructible_v<std::decay_t<T>, T>)
  1077. requires(inplace_proxiable_target<std::decay_t<T>, F>) {
  1078. return proxy<F>{std::in_place_type<details::inplace_ptr<std::decay_t<T>>>,
  1079. std::forward<T>(value)};
  1080. }
  1081. #if __STDC_HOSTED__
  1082. template <facade F, class T, class Alloc, class... Args>
  1083. proxy<F> allocate_proxy(const Alloc& alloc, Args&&... args) {
  1084. return details::allocate_proxy_impl<F, T>(alloc, std::forward<Args>(args)...);
  1085. }
  1086. template <facade F, class T, class Alloc, class U, class... Args>
  1087. proxy<F> allocate_proxy(const Alloc& alloc, std::initializer_list<U> il,
  1088. Args&&... args) {
  1089. return details::allocate_proxy_impl<F, T>(
  1090. alloc, il, std::forward<Args>(args)...);
  1091. }
  1092. template <facade F, class Alloc, class T>
  1093. proxy<F> allocate_proxy(const Alloc& alloc, T&& value) {
  1094. return details::allocate_proxy_impl<F, std::decay_t<T>>(
  1095. alloc, std::forward<T>(value));
  1096. }
  1097. template <facade F, class T, class... Args>
  1098. proxy<F> make_proxy(Args&&... args)
  1099. { return details::make_proxy_impl<F, T>(std::forward<Args>(args)...); }
  1100. template <facade F, class T, class U, class... Args>
  1101. proxy<F> make_proxy(std::initializer_list<U> il, Args&&... args)
  1102. { return details::make_proxy_impl<F, T>(il, std::forward<Args>(args)...); }
  1103. template <facade F, class T>
  1104. proxy<F> make_proxy(T&& value) {
  1105. return details::make_proxy_impl<F, std::decay_t<T>>(std::forward<T>(value));
  1106. }
  1107. #endif // __STDC_HOSTED__
  1108. template <class F>
  1109. struct observer_facade;
  1110. template <class F>
  1111. using proxy_view = proxy<observer_facade<F>>;
  1112. #define ___PRO_DIRECT_FUNC_IMPL(...) \
  1113. noexcept(noexcept(__VA_ARGS__)) requires(requires { __VA_ARGS__; }) \
  1114. { return __VA_ARGS__; }
  1115. #define ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(__MACRO, ...) \
  1116. template <class __F, bool __IsDirect, class __D, class... __Os> \
  1117. struct ___PRO_ENFORCE_EBO accessor { accessor() = delete; }; \
  1118. template <class __F, bool __IsDirect, class __D, class... __Os> \
  1119. requires(sizeof...(__Os) > 1u && (::std::is_constructible_v< \
  1120. accessor<__F, __IsDirect, __D, __Os>> && ...)) \
  1121. struct accessor<__F, __IsDirect, __D, __Os...> \
  1122. : accessor<__F, __IsDirect, __D, __Os>... \
  1123. { using accessor<__F, __IsDirect, __D, __Os>::__VA_ARGS__...; }; \
  1124. __MACRO(, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
  1125. __MACRO(noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
  1126. __MACRO(&, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
  1127. __MACRO(& noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
  1128. __MACRO(&&, ::pro::access_proxy<__F>(::std::move(*this)), __VA_ARGS__); \
  1129. __MACRO(&& noexcept, ::pro::access_proxy<__F>(::std::move(*this)), \
  1130. __VA_ARGS__); \
  1131. __MACRO(const, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
  1132. __MACRO(const noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
  1133. __MACRO(const&, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
  1134. __MACRO(const& noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
  1135. __MACRO(const&&, ::pro::access_proxy<__F>(::std::move(*this)), \
  1136. __VA_ARGS__); \
  1137. __MACRO(const&& noexcept, ::pro::access_proxy<__F>(::std::move(*this)), \
  1138. __VA_ARGS__);
  1139. #define ___PRO_ADL_ARG ::pro::details::adl_accessor_arg_t<__F, __IsDirect>
  1140. #define ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(__MACRO, ...) \
  1141. template <class __F, bool __IsDirect, class __D, class... __Os> \
  1142. struct ___PRO_ENFORCE_EBO accessor { accessor() = delete; }; \
  1143. template <class __F, bool __IsDirect, class __D, class... __Os> \
  1144. requires(sizeof...(__Os) > 1u && (::std::is_constructible_v< \
  1145. accessor<__F, __IsDirect, __D, __Os>> && ...)) \
  1146. struct accessor<__F, __IsDirect, __D, __Os...> \
  1147. : accessor<__F, __IsDirect, __D, __Os>... {}; \
  1148. __MACRO(,, ___PRO_ADL_ARG& __self, ::pro::access_proxy<__F>(__self), \
  1149. __VA_ARGS__); \
  1150. __MACRO(noexcept, noexcept, ___PRO_ADL_ARG& __self, \
  1151. ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
  1152. __MACRO(&,, ___PRO_ADL_ARG& __self, ::pro::access_proxy<__F>(__self), \
  1153. __VA_ARGS__); \
  1154. __MACRO(& noexcept, noexcept, ___PRO_ADL_ARG& __self, \
  1155. ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
  1156. __MACRO(&&,, ___PRO_ADL_ARG&& __self, ::pro::access_proxy<__F>( \
  1157. ::std::forward<decltype(__self)>(__self)), __VA_ARGS__); \
  1158. __MACRO(&& noexcept, noexcept, ___PRO_ADL_ARG&& __self, \
  1159. ::pro::access_proxy<__F>(::std::forward<decltype(__self)>(__self)), \
  1160. __VA_ARGS__); \
  1161. __MACRO(const,, const ___PRO_ADL_ARG& __self, \
  1162. ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
  1163. __MACRO(const noexcept, noexcept, const ___PRO_ADL_ARG& __self, \
  1164. ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
  1165. __MACRO(const&,, const ___PRO_ADL_ARG& __self, \
  1166. ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
  1167. __MACRO(const& noexcept, noexcept, const ___PRO_ADL_ARG& __self, \
  1168. ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
  1169. __MACRO(const&&,, const ___PRO_ADL_ARG&& __self, ::pro::access_proxy<__F>( \
  1170. ::std::forward<decltype(__self)>(__self)), __VA_ARGS__); \
  1171. __MACRO(const&& noexcept, noexcept, const ___PRO_ADL_ARG&& __self, \
  1172. ::pro::access_proxy<__F>(::std::forward<decltype(__self)>(__self)), \
  1173. __VA_ARGS__);
  1174. #define ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(...) \
  1175. ___PRO_DEBUG( \
  1176. accessor() noexcept { ::std::ignore = &accessor::__VA_ARGS__; })
  1177. #ifdef __cpp_rtti
  1178. class bad_proxy_cast : public std::bad_cast {
  1179. public:
  1180. char const* what() const noexcept override { return "pro::bad_proxy_cast"; }
  1181. };
  1182. #endif // __cpp_rtti
  1183. namespace details {
  1184. template <class F, bool IsDirect>
  1185. using adl_accessor_arg_t =
  1186. std::conditional_t<IsDirect, proxy<F>, proxy_indirect_accessor<F>>;
  1187. #define ___PRO_DEF_CAST_ACCESSOR(Q, SELF, ...) \
  1188. template <class __F, bool __IsDirect, class __D, class T> \
  1189. struct accessor<__F, __IsDirect, __D, T() Q> { \
  1190. ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(operator T) \
  1191. explicit(Expl) operator T() Q { \
  1192. if constexpr (Nullable) { \
  1193. if (!SELF.has_value()) { return nullptr; } \
  1194. } \
  1195. return proxy_invoke<__IsDirect, __D, T() Q>(SELF); \
  1196. } \
  1197. }
  1198. template <bool Expl, bool Nullable>
  1199. struct cast_dispatch_base {
  1200. ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_CAST_ACCESSOR,
  1201. operator typename overload_traits<__Os>::return_type)
  1202. };
  1203. #undef ___PRO_DEF_CAST_ACCESSOR
  1204. struct upward_conversion_dispatch : cast_dispatch_base<false, true> {
  1205. template <class T>
  1206. T&& operator()(T&& self) const noexcept { return std::forward<T>(self); }
  1207. };
  1208. template <class T>
  1209. struct explicit_conversion_adapter {
  1210. explicit explicit_conversion_adapter(T&& value) noexcept
  1211. : value_(std::forward<T>(value)) {}
  1212. explicit_conversion_adapter(const explicit_conversion_adapter&) = delete;
  1213. template <class U>
  1214. operator U() const noexcept(std::is_nothrow_constructible_v<U, T>)
  1215. requires(std::is_constructible_v<U, T>)
  1216. { return U{std::forward<T>(value_)}; }
  1217. private:
  1218. T&& value_;
  1219. };
  1220. constexpr std::size_t invalid_size = std::numeric_limits<std::size_t>::max();
  1221. constexpr constraint_level invalid_cl = static_cast<constraint_level>(
  1222. std::numeric_limits<std::underlying_type_t<constraint_level>>::min());
  1223. consteval auto normalize(proxiable_ptr_constraints value) {
  1224. if (value.max_size == invalid_size)
  1225. { value.max_size = sizeof(ptr_prototype); }
  1226. if (value.max_align == invalid_size)
  1227. { value.max_align = alignof(ptr_prototype); }
  1228. if (value.copyability == invalid_cl)
  1229. { value.copyability = constraint_level::none; }
  1230. if (value.relocatability == invalid_cl)
  1231. { value.relocatability = constraint_level::nothrow; }
  1232. if (value.destructibility == invalid_cl)
  1233. { value.destructibility = constraint_level::nothrow; }
  1234. return value;
  1235. }
  1236. consteval auto make_restricted_layout(proxiable_ptr_constraints value,
  1237. std::size_t max_size, std::size_t max_align) {
  1238. if (value.max_size > max_size) { value.max_size = max_size; }
  1239. if (value.max_align > max_align) { value.max_align = max_align; }
  1240. return value;
  1241. }
  1242. consteval auto make_copyable(proxiable_ptr_constraints value,
  1243. constraint_level cl) {
  1244. if (value.copyability < cl) { value.copyability = cl; }
  1245. return value;
  1246. }
  1247. consteval auto make_relocatable(proxiable_ptr_constraints value,
  1248. constraint_level cl) {
  1249. if (value.relocatability < cl) { value.relocatability = cl; }
  1250. return value;
  1251. }
  1252. consteval auto make_destructible(proxiable_ptr_constraints value,
  1253. constraint_level cl) {
  1254. if (value.destructibility < cl) { value.destructibility = cl; }
  1255. return value;
  1256. }
  1257. consteval auto merge_constraints(proxiable_ptr_constraints a,
  1258. proxiable_ptr_constraints b) {
  1259. a = make_restricted_layout(a, b.max_size, b.max_align);
  1260. a = make_copyable(a, b.copyability);
  1261. a = make_relocatable(a, b.relocatability);
  1262. a = make_destructible(a, b.destructibility);
  1263. return a;
  1264. }
  1265. consteval std::size_t max_align_of(std::size_t value) {
  1266. value &= ~value + 1u;
  1267. return value < alignof(std::max_align_t) ? value : alignof(std::max_align_t);
  1268. }
  1269. template <class SFINAE, class T, class F, bool IsDirect, class... Args>
  1270. struct accessor_instantiation_traits : std::type_identity<void> {};
  1271. template <class T, class F, bool IsDirect, class... Args>
  1272. struct accessor_instantiation_traits<std::void_t<typename T::template accessor<
  1273. F, IsDirect, T, Args...>>, T, F, IsDirect, Args...>
  1274. : std::type_identity<typename T::template accessor<
  1275. F, IsDirect, T, Args...>> {};
  1276. template <class T, class F, bool IsDirect, class... Args>
  1277. using instantiated_accessor_t =
  1278. typename accessor_instantiation_traits<void, T, F, IsDirect, Args...>::type;
  1279. template <bool IsDirect, class D, class... Os>
  1280. struct conv_impl {
  1281. static constexpr bool is_direct = IsDirect;
  1282. using dispatch_type = D;
  1283. using overload_types = std::tuple<Os...>;
  1284. template <class F>
  1285. using accessor = instantiated_accessor_t<D, F, IsDirect, Os...>;
  1286. };
  1287. template <bool IsDirect, class R>
  1288. struct refl_impl {
  1289. static constexpr bool is_direct = IsDirect;
  1290. using reflector_type = R;
  1291. template <class F>
  1292. using accessor = instantiated_accessor_t<R, F, IsDirect>;
  1293. };
  1294. template <class Cs, class Rs, proxiable_ptr_constraints C>
  1295. struct facade_impl {
  1296. using convention_types = Cs;
  1297. using reflection_types = Rs;
  1298. static constexpr proxiable_ptr_constraints constraints = C;
  1299. };
  1300. template <class O, class I>
  1301. struct add_tuple_reduction : std::type_identity<O> {};
  1302. template <class... Os, class I> requires(!std::is_same_v<I, Os> && ...)
  1303. struct add_tuple_reduction<std::tuple<Os...>, I>
  1304. : std::type_identity<std::tuple<Os..., I>> {};
  1305. template <class T, class U>
  1306. using add_tuple_t = typename add_tuple_reduction<T, U>::type;
  1307. template <class O, class... Is>
  1308. using merge_tuple_impl_t = recursive_reduction_t<add_tuple_t, O, Is...>;
  1309. template <class T, class U>
  1310. using merge_tuple_t = instantiated_t<merge_tuple_impl_t, U, T>;
  1311. template <bool IsDirect, class D>
  1312. struct merge_conv_traits
  1313. { template <class... Os> using type = conv_impl<IsDirect, D, Os...>; };
  1314. template <class C1, class C2>
  1315. using merge_conv_t = instantiated_t<
  1316. merge_conv_traits<C1::is_direct, typename C1::dispatch_type>::template type,
  1317. merge_tuple_t<typename C1::overload_types, typename C2::overload_types>>;
  1318. template <class Cs1, class C2, class C> struct add_conv_reduction;
  1319. template <class... Cs1, class C2, class... Cs3, class C>
  1320. struct add_conv_reduction<std::tuple<Cs1...>, std::tuple<C2, Cs3...>, C>
  1321. : add_conv_reduction<std::tuple<Cs1..., C2>, std::tuple<Cs3...>, C> {};
  1322. template <class... Cs1, class C2, class... Cs3, class C>
  1323. requires(C::is_direct == C2::is_direct && std::is_same_v<
  1324. typename C::dispatch_type, typename C2::dispatch_type>)
  1325. struct add_conv_reduction<std::tuple<Cs1...>, std::tuple<C2, Cs3...>, C>
  1326. : std::type_identity<std::tuple<Cs1..., merge_conv_t<C2, C>, Cs3...>> {};
  1327. template <class... Cs, class C>
  1328. struct add_conv_reduction<std::tuple<Cs...>, std::tuple<>, C>
  1329. : std::type_identity<std::tuple<Cs..., merge_conv_t<
  1330. conv_impl<C::is_direct, typename C::dispatch_type>, C>>> {};
  1331. template <class Cs, class C>
  1332. using add_conv_t = typename add_conv_reduction<std::tuple<>, Cs, C>::type;
  1333. template <class F, constraint_level CL>
  1334. using copy_conversion_overload =
  1335. proxy<F>() const& noexcept(CL >= constraint_level::nothrow);
  1336. template <class F, constraint_level CL>
  1337. using move_conversion_overload =
  1338. proxy<F>() && noexcept(CL >= constraint_level::nothrow);
  1339. template <class Cs, class F, constraint_level CCL, constraint_level RCL>
  1340. struct add_upward_conversion_conv
  1341. : std::type_identity<add_conv_t<Cs, conv_impl<true,
  1342. upward_conversion_dispatch, copy_conversion_overload<F, CCL>,
  1343. move_conversion_overload<F, RCL>>>> {};
  1344. template <class Cs, class F, constraint_level RCL>
  1345. struct add_upward_conversion_conv<Cs, F, constraint_level::none, RCL>
  1346. : std::type_identity<add_conv_t<Cs, conv_impl<true,
  1347. upward_conversion_dispatch, move_conversion_overload<F, RCL>>>> {};
  1348. template <class Cs, class F, constraint_level CCL>
  1349. struct add_upward_conversion_conv<Cs, F, CCL, constraint_level::none>
  1350. : std::type_identity<add_conv_t<Cs, conv_impl<true,
  1351. upward_conversion_dispatch, copy_conversion_overload<F, CCL>>>> {};
  1352. template <class Cs, class F>
  1353. struct add_upward_conversion_conv<
  1354. Cs, F, constraint_level::none, constraint_level::none>
  1355. : std::type_identity<Cs> {};
  1356. template <class Cs1, class... Cs2>
  1357. using merge_conv_tuple_t = recursive_reduction_t<add_conv_t, Cs1, Cs2...>;
  1358. template <class Cs, class F, bool WithUpwardConversion>
  1359. using merge_facade_conv_t = typename add_upward_conversion_conv<
  1360. instantiated_t<merge_conv_tuple_t, typename F::convention_types, Cs>, F,
  1361. WithUpwardConversion ? F::constraints.copyability : constraint_level::none,
  1362. (WithUpwardConversion &&
  1363. F::constraints.copyability != constraint_level::trivial) ?
  1364. F::constraints.relocatability : constraint_level::none>::type;
  1365. struct proxy_view_dispatch : cast_dispatch_base<false, true> {
  1366. template <class T>
  1367. auto* operator()(T&& value) const
  1368. ___PRO_DIRECT_FUNC_IMPL(std::addressof(*std::forward<T>(value)))
  1369. };
  1370. template <class P> struct facade_of_traits;
  1371. template <class F>
  1372. struct facade_of_traits<proxy<F>> : std::type_identity<F> {};
  1373. template <class P> using facade_of_t = typename facade_of_traits<P>::type;
  1374. template <class F, bool IsDirect, class D, class O>
  1375. struct observer_overload_mapping_traits_impl
  1376. : std::type_identity<typename overload_traits<O>::view_type> {};
  1377. template <class F, class D, class O>
  1378. requires(!std::is_same_v<D, proxy_view_dispatch> ||
  1379. std::is_same_v<typename overload_traits<O>::return_type, proxy_view<F>>)
  1380. struct observer_overload_mapping_traits_impl<F, true, D, O>
  1381. : std::type_identity<void> {};
  1382. template <class F, bool IsDirect, class D, class O>
  1383. struct observer_overload_mapping_traits : std::type_identity<void> {};
  1384. template <class F, bool IsDirect, class D, class O>
  1385. requires(overload_traits<O>::qualifier ==
  1386. (std::is_const_v<F> ? qualifier_type::const_lv : qualifier_type::lv))
  1387. struct observer_overload_mapping_traits<F, IsDirect, D, O>
  1388. : observer_overload_mapping_traits_impl<F, IsDirect, D, O> {};
  1389. template <class F, class O>
  1390. struct observer_overload_mapping_traits<F, true, upward_conversion_dispatch, O>
  1391. : std::type_identity<proxy_view<std::conditional_t<std::is_const_v<F>,
  1392. const facade_of_t<typename overload_traits<O>::return_type>,
  1393. facade_of_t<typename overload_traits<O>::return_type>>>()
  1394. const noexcept> {};
  1395. template <class D>
  1396. struct observer_dispatch_reduction : std::type_identity<D> {};
  1397. template <>
  1398. struct observer_dispatch_reduction<upward_conversion_dispatch>
  1399. : std::type_identity<proxy_view_dispatch> {};
  1400. template <class O, class I>
  1401. struct observer_overload_ignore_void_reduction : std::type_identity<O> {};
  1402. template <bool IsDirect, class D, class... Os, class O>
  1403. requires(!std::is_void_v<O>)
  1404. struct observer_overload_ignore_void_reduction<conv_impl<IsDirect, D, Os...>, O>
  1405. : std::type_identity<conv_impl<IsDirect, D, Os..., O>> {};
  1406. template <class O, class I>
  1407. using observer_overload_ignore_void_reduction_t =
  1408. typename observer_overload_ignore_void_reduction<O, I>::type;
  1409. template <class F, class C, class... Os>
  1410. using observer_conv_impl = recursive_reduction_t<
  1411. observer_overload_ignore_void_reduction_t,
  1412. conv_impl<C::is_direct, typename observer_dispatch_reduction<
  1413. typename C::dispatch_type>::type>,
  1414. typename observer_overload_mapping_traits<
  1415. F, C::is_direct, typename C::dispatch_type, Os>::type...>;
  1416. template <class O, class I>
  1417. struct observer_conv_reduction : std::type_identity<O> {};
  1418. template <class O, class I>
  1419. requires(std::tuple_size_v<typename I::overload_types> != 0u)
  1420. struct observer_conv_reduction<O, I> : std::type_identity<add_conv_t<O, I>> {};
  1421. template <class F>
  1422. struct observer_conv_reduction_traits {
  1423. template <class O, class I>
  1424. using type = typename observer_conv_reduction<O, instantiated_t<
  1425. observer_conv_impl, typename I::overload_types, F, I>>::type;
  1426. };
  1427. template <class O, class I>
  1428. struct observer_refl_reduction : std::type_identity<O> {};
  1429. template <class... Rs, class R> requires(!R::is_direct)
  1430. struct observer_refl_reduction<std::tuple<Rs...>, R>
  1431. : std::type_identity<std::tuple<Rs..., R>> {};
  1432. template <class O, class I>
  1433. using observer_refl_reduction_t = typename observer_refl_reduction<O, I>::type;
  1434. template <class F, class... Cs>
  1435. struct observer_facade_conv_impl {
  1436. using convention_types = recursive_reduction_t<
  1437. observer_conv_reduction_traits<F>::template type, std::tuple<>, Cs...>;
  1438. };
  1439. template <class... Rs>
  1440. struct observer_facade_refl_impl {
  1441. using reflection_types = recursive_reduction_t<
  1442. observer_refl_reduction_t, std::tuple<>, Rs...>;
  1443. };
  1444. template <class F>
  1445. struct proxy_view_overload_traits
  1446. : std::type_identity<proxy_view<F>() noexcept> {};
  1447. template <class F>
  1448. struct proxy_view_overload_traits<const F>
  1449. : std::type_identity<proxy_view<const F>() const noexcept> {};
  1450. template <class F>
  1451. using proxy_view_overload = typename proxy_view_overload_traits<F>::type;
  1452. template <std::size_t N>
  1453. struct sign {
  1454. consteval sign(const char (&str)[N])
  1455. { for (std::size_t i = 0; i < N; ++i) { value[i] = str[i]; } }
  1456. char value[N];
  1457. };
  1458. template <std::size_t N>
  1459. sign(const char (&str)[N]) -> sign<N>;
  1460. #if __STDC_HOSTED__
  1461. template <class CharT> struct format_overload_traits;
  1462. template <>
  1463. struct format_overload_traits<char>
  1464. : std::type_identity<std::format_context::iterator(
  1465. std::string_view spec, std::format_context& fc) const> {};
  1466. template <>
  1467. struct format_overload_traits<wchar_t>
  1468. : std::type_identity<std::wformat_context::iterator(
  1469. std::wstring_view spec, std::wformat_context& fc) const> {};
  1470. template <class CharT>
  1471. using format_overload_t = typename format_overload_traits<CharT>::type;
  1472. struct format_dispatch {
  1473. // Note: This function requires std::formatter<T, CharT> to be well-formed.
  1474. // However, the standard did not provide such facility before C++23. In the
  1475. // "required" clause of this function, std::formattable (C++23) is preferred
  1476. // when available. Otherwise, when building with C++20, we simply check
  1477. // whether std::formatter<T, CharT> is a disabled specialization of
  1478. // std::formatter by std::is_default_constructible_v as per
  1479. // [format.formatter.spec].
  1480. template <class T, class CharT, class OutIt>
  1481. OutIt operator()(const T& self, std::basic_string_view<CharT> spec,
  1482. std::basic_format_context<OutIt, CharT>& fc) const
  1483. requires(
  1484. #if defined(__cpp_lib_format_ranges) && __cpp_lib_format_ranges >= 202207L
  1485. std::formattable<T, CharT>
  1486. #else
  1487. std::is_default_constructible_v<std::formatter<T, CharT>>
  1488. #endif // defined(__cpp_lib_format_ranges) && __cpp_lib_format_ranges >= 202207L
  1489. ) {
  1490. std::formatter<T, CharT> impl;
  1491. {
  1492. std::basic_format_parse_context<CharT> pc{spec};
  1493. impl.parse(pc);
  1494. }
  1495. return impl.format(self, fc);
  1496. }
  1497. };
  1498. #endif // __STDC_HOSTED__
  1499. #ifdef __cpp_rtti
  1500. struct proxy_cast_context {
  1501. const std::type_info* type_ptr;
  1502. bool is_ref;
  1503. bool is_const;
  1504. void* result_ptr;
  1505. };
  1506. struct proxy_cast_dispatch;
  1507. template <class F, bool IsDirect, class D, class O>
  1508. struct proxy_cast_accessor_impl {
  1509. using _Self = add_qualifier_t<
  1510. adl_accessor_arg_t<F, IsDirect>, overload_traits<O>::qualifier>;
  1511. template <class T>
  1512. friend T proxy_cast(_Self self) {
  1513. static_assert(!std::is_rvalue_reference_v<T>);
  1514. if (!access_proxy<F>(self).has_value()) { ___PRO_THROW(bad_proxy_cast{}); }
  1515. if constexpr (std::is_lvalue_reference_v<T>) {
  1516. using U = std::remove_reference_t<T>;
  1517. void* result = nullptr;
  1518. proxy_cast_context ctx{.type_ptr = &typeid(T), .is_ref = true,
  1519. .is_const = std::is_const_v<U>, .result_ptr = &result};
  1520. proxy_invoke<IsDirect, D, O>(
  1521. access_proxy<F>(std::forward<_Self>(self)), ctx);
  1522. if (result == nullptr) { ___PRO_THROW(bad_proxy_cast{}); }
  1523. return *static_cast<U*>(result);
  1524. } else {
  1525. std::optional<std::remove_const_t<T>> result;
  1526. proxy_cast_context ctx{.type_ptr = &typeid(T), .is_ref = false,
  1527. .is_const = false, .result_ptr = &result};
  1528. proxy_invoke<IsDirect, D, O>(
  1529. access_proxy<F>(std::forward<_Self>(self)), ctx);
  1530. if (!result.has_value()) { ___PRO_THROW(bad_proxy_cast{}); }
  1531. return std::move(*result);
  1532. }
  1533. }
  1534. template <class T>
  1535. friend T* proxy_cast(std::remove_reference_t<_Self>* self) noexcept
  1536. requires(std::is_lvalue_reference_v<_Self>) {
  1537. if (!access_proxy<F>(*self).has_value()) { return nullptr; }
  1538. void* result = nullptr;
  1539. proxy_cast_context ctx{.type_ptr = &typeid(T), .is_ref = true,
  1540. .is_const = std::is_const_v<T>, .result_ptr = &result};
  1541. proxy_invoke<IsDirect, D, O>(access_proxy<F>(*self), ctx);
  1542. return static_cast<T*>(result);
  1543. }
  1544. };
  1545. #define ___PRO_DEF_PROXY_CAST_ACCESSOR(Q, ...) \
  1546. template <class F, bool IsDirect, class D> \
  1547. struct accessor<F, IsDirect, D, void(proxy_cast_context) Q> \
  1548. : proxy_cast_accessor_impl<F, IsDirect, D, \
  1549. void(proxy_cast_context) Q> {}
  1550. struct proxy_cast_dispatch {
  1551. template <class T>
  1552. void operator()(T&& self, proxy_cast_context ctx) const {
  1553. if (typeid(T) == *ctx.type_ptr) {
  1554. if (ctx.is_ref) {
  1555. if constexpr (std::is_lvalue_reference_v<T>) {
  1556. if (ctx.is_const || !std::is_const_v<T>) {
  1557. *static_cast<void**>(ctx.result_ptr) = (void*)&self;
  1558. }
  1559. }
  1560. } else {
  1561. if constexpr (std::is_constructible_v<std::decay_t<T>, T>) {
  1562. static_cast<std::optional<std::decay_t<T>>*>(ctx.result_ptr)
  1563. ->emplace(std::forward<T>(self));
  1564. }
  1565. }
  1566. }
  1567. }
  1568. ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_PROXY_CAST_ACCESSOR)
  1569. };
  1570. #undef ___PRO_DEF_PROXY_CAST_ACCESSOR
  1571. struct proxy_typeid_reflector {
  1572. template <class T>
  1573. constexpr explicit proxy_typeid_reflector(std::in_place_type_t<T>)
  1574. : info(&typeid(T)) {}
  1575. constexpr proxy_typeid_reflector(const proxy_typeid_reflector&) = default;
  1576. template <class F, bool IsDirect, class R>
  1577. struct accessor {
  1578. friend const std::type_info& proxy_typeid(
  1579. const adl_accessor_arg_t<F, IsDirect>& self) noexcept {
  1580. const proxy<F>& p = access_proxy<F>(self);
  1581. if (!p.has_value()) { return typeid(void); }
  1582. const proxy_typeid_reflector& refl = proxy_reflect<IsDirect, R>(p);
  1583. return *refl.info;
  1584. }
  1585. ___PRO_DEBUG(
  1586. accessor() noexcept { std::ignore = &accessor::_symbol_guard; }
  1587. private:
  1588. static inline const std::type_info& _symbol_guard(
  1589. const adl_accessor_arg_t<F, IsDirect>& self) noexcept
  1590. { return proxy_typeid(self); }
  1591. )
  1592. };
  1593. const std::type_info* info;
  1594. };
  1595. #endif // __cpp_rtti
  1596. struct wildcard {
  1597. wildcard() = delete;
  1598. template <class T>
  1599. [[noreturn]] operator T() const {
  1600. #ifdef __cpp_lib_unreachable
  1601. std::unreachable();
  1602. #else
  1603. std::abort();
  1604. #endif // __cpp_lib_unreachable
  1605. }
  1606. };
  1607. } // namespace details
  1608. template <class Cs, class Rs, proxiable_ptr_constraints C>
  1609. struct basic_facade_builder {
  1610. template <class D, class... Os>
  1611. requires(sizeof...(Os) > 0u &&
  1612. (details::overload_traits<Os>::applicable && ...))
  1613. using add_indirect_convention = basic_facade_builder<details::add_conv_t<
  1614. Cs, details::conv_impl<false, D, Os...>>, Rs, C>;
  1615. template <class D, class... Os>
  1616. requires(sizeof...(Os) > 0u &&
  1617. (details::overload_traits<Os>::applicable && ...))
  1618. using add_direct_convention = basic_facade_builder<details::add_conv_t<
  1619. Cs, details::conv_impl<true, D, Os...>>, Rs, C>;
  1620. template <class D, class... Os>
  1621. requires(sizeof...(Os) > 0u &&
  1622. (details::overload_traits<Os>::applicable && ...))
  1623. using add_convention = add_indirect_convention<D, Os...>;
  1624. template <class R>
  1625. using add_indirect_reflection = basic_facade_builder<
  1626. Cs, details::add_tuple_t<Rs, details::refl_impl<false, R>>, C>;
  1627. template <class R>
  1628. using add_direct_reflection = basic_facade_builder<
  1629. Cs, details::add_tuple_t<Rs, details::refl_impl<true, R>>, C>;
  1630. template <class R>
  1631. using add_reflection = add_indirect_reflection<R>;
  1632. template <facade F, bool WithUpwardConversion = false>
  1633. using add_facade = basic_facade_builder<
  1634. details::merge_facade_conv_t<Cs, F, WithUpwardConversion>,
  1635. details::merge_tuple_t<Rs, typename F::reflection_types>,
  1636. details::merge_constraints(C, F::constraints)>;
  1637. template <std::size_t PtrSize,
  1638. std::size_t PtrAlign = details::max_align_of(PtrSize)>
  1639. requires(std::has_single_bit(PtrAlign) && PtrSize % PtrAlign == 0u)
  1640. using restrict_layout = basic_facade_builder<
  1641. Cs, Rs, details::make_restricted_layout(C, PtrSize, PtrAlign)>;
  1642. template <constraint_level CL>
  1643. using support_copy = basic_facade_builder<
  1644. Cs, Rs, details::make_copyable(C, CL)>;
  1645. template <constraint_level CL>
  1646. using support_relocation = basic_facade_builder<
  1647. Cs, Rs, details::make_relocatable(C, CL)>;
  1648. template <constraint_level CL>
  1649. using support_destruction = basic_facade_builder<
  1650. Cs, Rs, details::make_destructible(C, CL)>;
  1651. #if __STDC_HOSTED__
  1652. using support_format = add_convention<
  1653. details::format_dispatch, details::format_overload_t<char>>;
  1654. using support_wformat = add_convention<
  1655. details::format_dispatch, details::format_overload_t<wchar_t>>;
  1656. #endif // __STDC_HOSTED__
  1657. #ifdef __cpp_rtti
  1658. using support_indirect_rtti = basic_facade_builder<
  1659. details::add_conv_t<Cs, details::conv_impl<false,
  1660. details::proxy_cast_dispatch, void(details::proxy_cast_context) &,
  1661. void(details::proxy_cast_context) const&,
  1662. void(details::proxy_cast_context) &&>>,
  1663. details::add_tuple_t<Rs, details::refl_impl<false,
  1664. details::proxy_typeid_reflector>>, C>;
  1665. using support_direct_rtti = basic_facade_builder<
  1666. details::add_conv_t<Cs, details::conv_impl<true,
  1667. details::proxy_cast_dispatch, void(details::proxy_cast_context) &,
  1668. void(details::proxy_cast_context) const&,
  1669. void(details::proxy_cast_context) &&>>,
  1670. details::add_tuple_t<Rs, details::refl_impl<true,
  1671. details::proxy_typeid_reflector>>, C>;
  1672. using support_rtti = support_indirect_rtti;
  1673. #endif // __cpp_rtti
  1674. template <class F>
  1675. using add_view = add_direct_convention<
  1676. details::proxy_view_dispatch, details::proxy_view_overload<F>>;
  1677. using build = details::facade_impl<Cs, Rs, details::normalize(C)>;
  1678. basic_facade_builder() = delete;
  1679. };
  1680. template <class F>
  1681. struct observer_facade
  1682. : details::instantiated_t<details::observer_facade_conv_impl,
  1683. typename F::convention_types, F>,
  1684. details::instantiated_t<details::observer_facade_refl_impl,
  1685. typename F::reflection_types> {
  1686. static constexpr proxiable_ptr_constraints constraints{
  1687. .max_size = sizeof(void*), .max_align = alignof(void*),
  1688. .copyability = constraint_level::trivial,
  1689. .relocatability = constraint_level::trivial,
  1690. .destructibility = constraint_level::trivial};
  1691. };
  1692. using facade_builder = basic_facade_builder<std::tuple<>, std::tuple<>,
  1693. proxiable_ptr_constraints{
  1694. .max_size = details::invalid_size,
  1695. .max_align = details::invalid_size,
  1696. .copyability = details::invalid_cl,
  1697. .relocatability = details::invalid_cl,
  1698. .destructibility = details::invalid_cl}>;
  1699. template <details::sign Sign, bool Rhs = false>
  1700. struct operator_dispatch;
  1701. #define ___PRO_DEF_LHS_LEFT_OP_ACCESSOR(Q, SELF, ...) \
  1702. template <class __F, bool __IsDirect, class __D, class R> \
  1703. struct accessor<__F, __IsDirect, __D, R() Q> { \
  1704. ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
  1705. R __VA_ARGS__() Q { return proxy_invoke<__IsDirect, __D, R() Q>(SELF); } \
  1706. }
  1707. #define ___PRO_DEF_LHS_ANY_OP_ACCESSOR(Q, SELF, ...) \
  1708. template <class __F, bool __IsDirect, class __D, class R, class... Args> \
  1709. struct accessor<__F, __IsDirect, __D, R(Args...) Q> { \
  1710. ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
  1711. R __VA_ARGS__(Args... args) Q { \
  1712. return proxy_invoke<__IsDirect, __D, R(Args...) Q>( \
  1713. SELF, std::forward<Args>(args)...); \
  1714. } \
  1715. }
  1716. #define ___PRO_DEF_LHS_UNARY_OP_ACCESSOR ___PRO_DEF_LHS_ANY_OP_ACCESSOR
  1717. #define ___PRO_DEF_LHS_BINARY_OP_ACCESSOR ___PRO_DEF_LHS_ANY_OP_ACCESSOR
  1718. #define ___PRO_DEF_LHS_ALL_OP_ACCESSOR ___PRO_DEF_LHS_ANY_OP_ACCESSOR
  1719. #define ___PRO_LHS_LEFT_OP_DISPATCH_BODY_IMPL(...) \
  1720. template <class T> \
  1721. decltype(auto) operator()(T&& self) const \
  1722. ___PRO_DIRECT_FUNC_IMPL(__VA_ARGS__ std::forward<T>(self))
  1723. #define ___PRO_LHS_UNARY_OP_DISPATCH_BODY_IMPL(...) \
  1724. template <class T> \
  1725. decltype(auto) operator()(T&& self) const \
  1726. ___PRO_DIRECT_FUNC_IMPL(__VA_ARGS__ std::forward<T>(self)) \
  1727. template <class T> \
  1728. decltype(auto) operator()(T&& self, int) const \
  1729. ___PRO_DIRECT_FUNC_IMPL(std::forward<T>(self) __VA_ARGS__)
  1730. #define ___PRO_LHS_BINARY_OP_DISPATCH_BODY_IMPL(...) \
  1731. template <class T, class Arg> \
  1732. decltype(auto) operator()(T&& self, Arg&& arg) const \
  1733. ___PRO_DIRECT_FUNC_IMPL( \
  1734. std::forward<T>(self) __VA_ARGS__ std::forward<Arg>(arg))
  1735. #define ___PRO_LHS_ALL_OP_DISPATCH_BODY_IMPL(...) \
  1736. ___PRO_LHS_LEFT_OP_DISPATCH_BODY_IMPL(__VA_ARGS__) \
  1737. ___PRO_LHS_BINARY_OP_DISPATCH_BODY_IMPL(__VA_ARGS__)
  1738. #define ___PRO_LHS_OP_DISPATCH_IMPL(TYPE, ...) \
  1739. template <> \
  1740. struct operator_dispatch<#__VA_ARGS__, false> { \
  1741. ___PRO_LHS_##TYPE##_OP_DISPATCH_BODY_IMPL(__VA_ARGS__) \
  1742. ___PRO_DEF_MEM_ACCESSOR_TEMPLATE( \
  1743. ___PRO_DEF_LHS_##TYPE##_OP_ACCESSOR, operator __VA_ARGS__) \
  1744. };
  1745. #define ___PRO_DEF_RHS_OP_ACCESSOR(Q, NE, SELF_ARG, SELF, ...) \
  1746. template <class __F, bool __IsDirect, class __D, class R, class Arg> \
  1747. struct accessor<__F, __IsDirect, __D, R(Arg) Q> { \
  1748. friend R operator __VA_ARGS__(Arg arg, SELF_ARG) NE { \
  1749. return proxy_invoke<__IsDirect, __D, R(Arg) Q>( \
  1750. SELF, std::forward<Arg>(arg)); \
  1751. } \
  1752. ___PRO_DEBUG( \
  1753. accessor() noexcept { std::ignore = &accessor::_symbol_guard; } \
  1754. \
  1755. private: \
  1756. static inline R _symbol_guard(Arg arg, SELF_ARG) NE { \
  1757. return std::forward<Arg>(arg) __VA_ARGS__ \
  1758. std::forward<decltype(__self)>(__self); \
  1759. } \
  1760. ) \
  1761. }
  1762. #define ___PRO_RHS_OP_DISPATCH_IMPL(...) \
  1763. template <> \
  1764. struct operator_dispatch<#__VA_ARGS__, true> { \
  1765. template <class T, class Arg> \
  1766. decltype(auto) operator()(T&& self, Arg&& arg) const \
  1767. ___PRO_DIRECT_FUNC_IMPL( \
  1768. std::forward<Arg>(arg) __VA_ARGS__ std::forward<T>(self)) \
  1769. ___PRO_DEF_FREE_ACCESSOR_TEMPLATE( \
  1770. ___PRO_DEF_RHS_OP_ACCESSOR, __VA_ARGS__) \
  1771. };
  1772. #define ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL(...) \
  1773. ___PRO_LHS_OP_DISPATCH_IMPL(ALL, __VA_ARGS__) \
  1774. ___PRO_RHS_OP_DISPATCH_IMPL(__VA_ARGS__)
  1775. #define ___PRO_BINARY_OP_DISPATCH_IMPL(...) \
  1776. ___PRO_LHS_OP_DISPATCH_IMPL(BINARY, __VA_ARGS__) \
  1777. ___PRO_RHS_OP_DISPATCH_IMPL(__VA_ARGS__)
  1778. #define ___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR(Q, SELF, ...) \
  1779. template <class __F, bool __IsDirect, class __D, class R, class Arg> \
  1780. struct accessor<__F, __IsDirect, __D, R(Arg) Q> { \
  1781. ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
  1782. decltype(auto) __VA_ARGS__(Arg arg) Q { \
  1783. proxy_invoke<__IsDirect, __D, R(Arg) Q>(SELF, std::forward<Arg>(arg)); \
  1784. if constexpr (__IsDirect) { \
  1785. return SELF; \
  1786. } else { \
  1787. return *SELF; \
  1788. } \
  1789. } \
  1790. }
  1791. #define ___PRO_DEF_RHS_ASSIGNMENT_OP_ACCESSOR(Q, NE, SELF_ARG, SELF, ...) \
  1792. template <class __F, bool __IsDirect, class __D, class R, class Arg> \
  1793. struct accessor<__F, __IsDirect, __D, R(Arg&) Q> { \
  1794. friend Arg& operator __VA_ARGS__(Arg& arg, SELF_ARG) NE { \
  1795. proxy_invoke<__IsDirect, __D, R(Arg&) Q>(SELF, arg); \
  1796. return arg; \
  1797. } \
  1798. ___PRO_DEBUG( \
  1799. accessor() noexcept { std::ignore = &accessor::_symbol_guard; } \
  1800. \
  1801. private: \
  1802. static inline Arg& _symbol_guard(Arg& arg, SELF_ARG) NE \
  1803. { return arg __VA_ARGS__ std::forward<decltype(__self)>(__self); } \
  1804. ) \
  1805. }
  1806. #define ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(...) \
  1807. template <> \
  1808. struct operator_dispatch<#__VA_ARGS__, false> { \
  1809. template <class T, class Arg> \
  1810. decltype(auto) operator()(T&& self, Arg&& arg) const \
  1811. ___PRO_DIRECT_FUNC_IMPL(std::forward<T>(self) __VA_ARGS__ \
  1812. std::forward<Arg>(arg)) \
  1813. ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR, \
  1814. operator __VA_ARGS__) \
  1815. }; \
  1816. template <> \
  1817. struct operator_dispatch<#__VA_ARGS__, true> { \
  1818. template <class T, class Arg> \
  1819. decltype(auto) operator()(T&& self, Arg&& arg) const \
  1820. ___PRO_DIRECT_FUNC_IMPL( \
  1821. std::forward<Arg>(arg) __VA_ARGS__ std::forward<T>(self)) \
  1822. ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_RHS_ASSIGNMENT_OP_ACCESSOR, \
  1823. __VA_ARGS__) \
  1824. };
  1825. ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL(+)
  1826. ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL(-)
  1827. ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL(*)
  1828. ___PRO_BINARY_OP_DISPATCH_IMPL(/)
  1829. ___PRO_BINARY_OP_DISPATCH_IMPL(%)
  1830. ___PRO_LHS_OP_DISPATCH_IMPL(UNARY, ++)
  1831. ___PRO_LHS_OP_DISPATCH_IMPL(UNARY, --)
  1832. ___PRO_BINARY_OP_DISPATCH_IMPL(==)
  1833. ___PRO_BINARY_OP_DISPATCH_IMPL(!=)
  1834. ___PRO_BINARY_OP_DISPATCH_IMPL(>)
  1835. ___PRO_BINARY_OP_DISPATCH_IMPL(<)
  1836. ___PRO_BINARY_OP_DISPATCH_IMPL(>=)
  1837. ___PRO_BINARY_OP_DISPATCH_IMPL(<=)
  1838. ___PRO_BINARY_OP_DISPATCH_IMPL(<=>)
  1839. ___PRO_LHS_OP_DISPATCH_IMPL(LEFT, !)
  1840. ___PRO_BINARY_OP_DISPATCH_IMPL(&&)
  1841. ___PRO_BINARY_OP_DISPATCH_IMPL(||)
  1842. ___PRO_LHS_OP_DISPATCH_IMPL(LEFT, ~)
  1843. ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL(&)
  1844. ___PRO_BINARY_OP_DISPATCH_IMPL(|)
  1845. ___PRO_BINARY_OP_DISPATCH_IMPL(^)
  1846. ___PRO_BINARY_OP_DISPATCH_IMPL(<<)
  1847. ___PRO_BINARY_OP_DISPATCH_IMPL(>>)
  1848. ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(+=)
  1849. ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(-=)
  1850. ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(*=)
  1851. ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(/=)
  1852. ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(&=)
  1853. ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(|=)
  1854. ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(^=)
  1855. ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(<<=)
  1856. ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(>>=)
  1857. ___PRO_BINARY_OP_DISPATCH_IMPL(,)
  1858. ___PRO_BINARY_OP_DISPATCH_IMPL(->*)
  1859. template <>
  1860. struct operator_dispatch<"()", false> {
  1861. template <class T, class... Args>
  1862. decltype(auto) operator()(T&& self, Args&&... args) const
  1863. ___PRO_DIRECT_FUNC_IMPL(
  1864. std::forward<T>(self)(std::forward<Args>(args)...))
  1865. ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ANY_OP_ACCESSOR, operator())
  1866. };
  1867. template <>
  1868. struct operator_dispatch<"[]", false> {
  1869. #if defined(__cpp_multidimensional_subscript) && __cpp_multidimensional_subscript >= 202110L
  1870. template <class T, class... Args>
  1871. decltype(auto) operator()(T&& self, Args&&... args) const
  1872. ___PRO_DIRECT_FUNC_IMPL(
  1873. std::forward<T>(self)[std::forward<Args>(args)...])
  1874. #else
  1875. template <class T, class Arg>
  1876. decltype(auto) operator()(T&& self, Arg&& arg) const
  1877. ___PRO_DIRECT_FUNC_IMPL(std::forward<T>(self)[std::forward<Arg>(arg)])
  1878. #endif // defined(__cpp_multidimensional_subscript) && __cpp_multidimensional_subscript >= 202110L
  1879. ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ANY_OP_ACCESSOR, operator[])
  1880. };
  1881. #undef ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL
  1882. #undef ___PRO_DEF_RHS_ASSIGNMENT_OP_ACCESSOR
  1883. #undef ___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR
  1884. #undef ___PRO_BINARY_OP_DISPATCH_IMPL
  1885. #undef ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL
  1886. #undef ___PRO_RHS_OP_DISPATCH_IMPL
  1887. #undef ___PRO_DEF_RHS_OP_ACCESSOR
  1888. #undef ___PRO_LHS_OP_DISPATCH_IMPL
  1889. #undef ___PRO_LHS_ALL_OP_DISPATCH_BODY_IMPL
  1890. #undef ___PRO_LHS_BINARY_OP_DISPATCH_BODY_IMPL
  1891. #undef ___PRO_LHS_UNARY_OP_DISPATCH_BODY_IMPL
  1892. #undef ___PRO_LHS_LEFT_OP_DISPATCH_BODY_IMPL
  1893. #undef ___PRO_DEF_LHS_ALL_OP_ACCESSOR
  1894. #undef ___PRO_DEF_LHS_BINARY_OP_ACCESSOR
  1895. #undef ___PRO_DEF_LHS_UNARY_OP_ACCESSOR
  1896. #undef ___PRO_DEF_LHS_ANY_OP_ACCESSOR
  1897. #undef ___PRO_DEF_LHS_LEFT_OP_ACCESSOR
  1898. struct implicit_conversion_dispatch
  1899. : details::cast_dispatch_base<false, false> {
  1900. template <class T>
  1901. T&& operator()(T&& self) const noexcept { return std::forward<T>(self); }
  1902. };
  1903. struct explicit_conversion_dispatch : details::cast_dispatch_base<true, false> {
  1904. template <class T>
  1905. auto operator()(T&& self) const noexcept
  1906. { return details::explicit_conversion_adapter<T>{std::forward<T>(self)}; }
  1907. };
  1908. using conversion_dispatch = explicit_conversion_dispatch;
  1909. class not_implemented : public std::exception {
  1910. public:
  1911. char const* what() const noexcept override { return "pro::not_implemented"; }
  1912. };
  1913. template <class D>
  1914. struct weak_dispatch : D {
  1915. using D::operator();
  1916. template <class... Args>
  1917. [[noreturn]] details::wildcard operator()(std::nullptr_t, Args&&...) const
  1918. { ___PRO_THROW(not_implemented{}); }
  1919. };
  1920. #define ___PRO_EXPAND_IMPL(__X) __X
  1921. #define ___PRO_EXPAND_MACRO_IMPL( \
  1922. __MACRO, __1, __2, __3, __NAME, ...) \
  1923. __MACRO##_##__NAME
  1924. #define ___PRO_EXPAND_MACRO(__MACRO, ...) \
  1925. ___PRO_EXPAND_IMPL(___PRO_EXPAND_MACRO_IMPL( \
  1926. __MACRO, __VA_ARGS__, 3, 2)(__VA_ARGS__))
  1927. #define ___PRO_DEF_MEM_ACCESSOR(__Q, __SELF, ...) \
  1928. template <class __F, bool __IsDirect, class __D, class __R, \
  1929. class... __Args> \
  1930. struct accessor<__F, __IsDirect, __D, __R(__Args...) __Q> { \
  1931. ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
  1932. __R __VA_ARGS__(__Args... __args) __Q { \
  1933. return ::pro::proxy_invoke<__IsDirect, __D, __R(__Args...) __Q>( \
  1934. __SELF, ::std::forward<__Args>(__args)...); \
  1935. } \
  1936. }
  1937. #define ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \
  1938. struct __NAME { \
  1939. template <class __T, class... __Args> \
  1940. decltype(auto) operator()(__T&& __self, __Args&&... __args) const \
  1941. ___PRO_DIRECT_FUNC_IMPL(::std::forward<__T>(__self) \
  1942. .__FUNC(::std::forward<__Args>(__args)...)) \
  1943. ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_MEM_ACCESSOR, __FNAME) \
  1944. }
  1945. #define ___PRO_DEF_MEM_DISPATCH_2(__NAME, __FUNC) \
  1946. ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FUNC)
  1947. #define ___PRO_DEF_MEM_DISPATCH_3(__NAME, __FUNC, __FNAME) \
  1948. ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME)
  1949. #define PRO_DEF_MEM_DISPATCH(__NAME, ...) \
  1950. ___PRO_EXPAND_MACRO(___PRO_DEF_MEM_DISPATCH, __NAME, __VA_ARGS__)
  1951. #define ___PRO_DEF_FREE_ACCESSOR(__Q, __NE, __SELF_ARG, __SELF, ...) \
  1952. template <class __F, bool __IsDirect, class __D, class __R, \
  1953. class... __Args> \
  1954. struct accessor<__F, __IsDirect, __D, __R(__Args...) __Q> { \
  1955. friend __R __VA_ARGS__(__SELF_ARG, __Args... __args) __NE { \
  1956. return ::pro::proxy_invoke<__IsDirect, __D, __R(__Args...) __Q>( \
  1957. __SELF, ::std::forward<__Args>(__args)...); \
  1958. } \
  1959. ___PRO_DEBUG( \
  1960. accessor() noexcept { ::std::ignore = &accessor::_symbol_guard; } \
  1961. \
  1962. private: \
  1963. static inline __R _symbol_guard(__SELF_ARG, __Args... __args) __NE { \
  1964. return __VA_ARGS__(::std::forward<decltype(__self)>(__self), \
  1965. ::std::forward<__Args>(__args)...); \
  1966. } \
  1967. ) \
  1968. }
  1969. #define ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \
  1970. struct __NAME { \
  1971. template <class __T, class... __Args> \
  1972. decltype(auto) operator()(__T&& __self, __Args&&... __args) const \
  1973. ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__T>(__self), \
  1974. ::std::forward<__Args>(__args)...)) \
  1975. ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_FREE_ACCESSOR, __FNAME) \
  1976. }
  1977. #define ___PRO_DEF_FREE_DISPATCH_2(__NAME, __FUNC) \
  1978. ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FUNC)
  1979. #define ___PRO_DEF_FREE_DISPATCH_3(__NAME, __FUNC, __FNAME) \
  1980. ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FNAME)
  1981. #define PRO_DEF_FREE_DISPATCH(__NAME, ...) \
  1982. ___PRO_EXPAND_MACRO(___PRO_DEF_FREE_DISPATCH, __NAME, __VA_ARGS__)
  1983. #define ___PRO_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \
  1984. struct __NAME { \
  1985. template <class __T, class... __Args> \
  1986. decltype(auto) operator()(__T&& __self, __Args&&... __args) const \
  1987. ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__T>(__self), \
  1988. ::std::forward<__Args>(__args)...)) \
  1989. ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_MEM_ACCESSOR, __FNAME) \
  1990. }
  1991. #define ___PRO_DEF_FREE_AS_MEM_DISPATCH_2(__NAME, __FUNC) \
  1992. ___PRO_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FUNC)
  1993. #define ___PRO_DEF_FREE_AS_MEM_DISPATCH_3(__NAME, __FUNC, __FNAME) \
  1994. ___PRO_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME)
  1995. #define PRO_DEF_FREE_AS_MEM_DISPATCH(__NAME, ...) \
  1996. ___PRO_EXPAND_MACRO(___PRO_DEF_FREE_AS_MEM_DISPATCH, __NAME, __VA_ARGS__)
  1997. #define PRO_DEF_WEAK_DISPATCH(__NAME, __D, __FUNC) \
  1998. struct [[deprecated("'PRO_DEF_WEAK_DISPATCH' is deprecated. " \
  1999. "Use pro::weak_dispatch<" #__D "> instead.")]] __NAME : __D { \
  2000. using __D::operator(); \
  2001. template <class... __Args> \
  2002. decltype(auto) operator()(::std::nullptr_t, __Args&&... __args) const \
  2003. ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__Args>(__args)...)) \
  2004. }
  2005. } // namespace pro
  2006. #if __STDC_HOSTED__
  2007. namespace std {
  2008. template <class F, class CharT>
  2009. requires(pro::details::facade_traits<F>::template is_invocable<false,
  2010. pro::details::format_dispatch, pro::details::format_overload_t<CharT>>)
  2011. struct formatter<pro::proxy_indirect_accessor<F>, CharT> {
  2012. constexpr auto parse(basic_format_parse_context<CharT>& pc) {
  2013. for (auto it = pc.begin(); it != pc.end(); ++it) {
  2014. if (*it == '}') {
  2015. spec_ = basic_string_view<CharT>{pc.begin(), it + 1};
  2016. return it;
  2017. }
  2018. }
  2019. return pc.end();
  2020. }
  2021. template <class OutIt>
  2022. OutIt format(const pro::proxy_indirect_accessor<F>& ia,
  2023. basic_format_context<OutIt, CharT>& fc) const {
  2024. auto& p = pro::access_proxy<F>(ia);
  2025. if (!p.has_value()) { ___PRO_THROW(format_error{"null proxy"}); }
  2026. return pro::proxy_invoke<false, pro::details::format_dispatch,
  2027. pro::details::format_overload_t<CharT>>(p, spec_, fc);
  2028. }
  2029. private:
  2030. basic_string_view<CharT> spec_;
  2031. };
  2032. } // namespace std
  2033. #endif // __STDC_HOSTED__
  2034. #undef ___PRO_THROW
  2035. #undef ___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE
  2036. #endif // _MSFT_PROXY_