| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194 |
- // Copyright (c) Microsoft Corporation.
- // Licensed under the MIT License.
- #ifndef _MSFT_PROXY_
- #define _MSFT_PROXY_
- #include <cassert>
- #include <cstddef>
- #include <cstdlib>
- #include <bit>
- #include <concepts>
- #include <exception>
- #include <initializer_list>
- #include <limits>
- #include <memory>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #if __STDC_HOSTED__
- #include <format>
- #endif // __STDC_HOSTED__
- #ifdef __cpp_rtti
- #include <optional>
- #include <typeinfo>
- #endif // __cpp_rtti
- #if __has_cpp_attribute(msvc::no_unique_address)
- #define ___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE msvc::no_unique_address
- #elif __has_cpp_attribute(no_unique_address)
- #define ___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE no_unique_address
- #else
- #error "Proxy requires C++20 attribute no_unique_address"
- #endif
- #ifdef __cpp_exceptions
- #define ___PRO_THROW(...) throw __VA_ARGS__
- #else
- #define ___PRO_THROW(...) std::abort()
- #endif // __cpp_exceptions
- #ifdef _MSC_VER
- #define ___PRO_ENFORCE_EBO __declspec(empty_bases)
- #else
- #define ___PRO_ENFORCE_EBO
- #endif // _MSC_VER
- #ifdef NDEBUG
- #define ___PRO_DEBUG(...)
- #else
- #define ___PRO_DEBUG(...) __VA_ARGS__
- #endif // NDEBUG
- #define __msft_lib_proxy 202501L
- namespace pro {
- enum class constraint_level { none, nontrivial, nothrow, trivial };
- struct proxiable_ptr_constraints {
- std::size_t max_size;
- std::size_t max_align;
- constraint_level copyability;
- constraint_level relocatability;
- constraint_level destructibility;
- };
- template <class F> struct proxy_indirect_accessor;
- template <class F> class proxy;
- namespace details {
- struct applicable_traits { static constexpr bool applicable = true; };
- struct inapplicable_traits { static constexpr bool applicable = false; };
- enum class qualifier_type { lv, const_lv, rv, const_rv };
- template <class T, qualifier_type Q> struct add_qualifier_traits;
- template <class T>
- struct add_qualifier_traits<T, qualifier_type::lv> : std::type_identity<T&> {};
- template <class T>
- struct add_qualifier_traits<T, qualifier_type::const_lv>
- : std::type_identity<const T&> {};
- template <class T>
- struct add_qualifier_traits<T, qualifier_type::rv> : std::type_identity<T&&> {};
- template <class T>
- struct add_qualifier_traits<T, qualifier_type::const_rv>
- : std::type_identity<const T&&> {};
- template <class T, qualifier_type Q>
- using add_qualifier_t = typename add_qualifier_traits<T, Q>::type;
- template <class T, qualifier_type Q>
- using add_qualifier_ptr_t = std::remove_reference_t<add_qualifier_t<T, Q>>*;
- template <template <class, class> class R, class O, class... Is>
- struct recursive_reduction : std::type_identity<O> {};
- template <template <class, class> class R, class O, class I, class... Is>
- struct recursive_reduction<R, O, I, Is...>
- : recursive_reduction<R, R<O, I>, Is...> {};
- template <template <class, class> class R, class O, class... Is>
- using recursive_reduction_t = typename recursive_reduction<R, O, Is...>::type;
- template <class Expr>
- consteval bool is_consteval(Expr)
- { return requires { typename std::bool_constant<(Expr{}(), false)>; }; }
- template <class T, std::size_t I>
- concept has_tuple_element = requires { typename std::tuple_element_t<I, T>; };
- template <class T>
- consteval bool is_tuple_like_well_formed() {
- if constexpr (requires { { std::tuple_size<T>::value } ->
- std::same_as<const std::size_t&>; }) {
- if constexpr (is_consteval([] { return std::tuple_size<T>::value; })) {
- return []<std::size_t... I>(std::index_sequence<I...>) {
- return (has_tuple_element<T, I> && ...);
- }(std::make_index_sequence<std::tuple_size_v<T>>{});
- }
- }
- return false;
- }
- template <template <class...> class T, class TL, class Is, class... Args>
- struct instantiated_traits;
- template <template <class...> class T, class TL, std::size_t... Is,
- class... Args>
- struct instantiated_traits<T, TL, std::index_sequence<Is...>, Args...>
- : std::type_identity<T<Args..., std::tuple_element_t<Is, TL>...>> {};
- template <template <class...> class T, class TL, class... Args>
- using instantiated_t = typename instantiated_traits<
- T, TL, std::make_index_sequence<std::tuple_size_v<TL>>, Args...>::type;
- template <class T>
- consteval bool has_copyability(constraint_level level) {
- switch (level) {
- case constraint_level::none: return true;
- case constraint_level::nontrivial: return std::is_copy_constructible_v<T>;
- case constraint_level::nothrow:
- return std::is_nothrow_copy_constructible_v<T>;
- case constraint_level::trivial:
- return std::is_trivially_copy_constructible_v<T> &&
- std::is_trivially_destructible_v<T>;
- default: return false;
- }
- }
- template <class T>
- consteval bool has_relocatability(constraint_level level) {
- switch (level) {
- case constraint_level::none: return true;
- case constraint_level::nontrivial:
- return std::is_move_constructible_v<T> && std::is_destructible_v<T>;
- case constraint_level::nothrow:
- return std::is_nothrow_move_constructible_v<T> &&
- std::is_nothrow_destructible_v<T>;
- case constraint_level::trivial:
- return std::is_trivially_move_constructible_v<T> &&
- std::is_trivially_destructible_v<T>;
- default: return false;
- }
- }
- template <class T>
- consteval bool has_destructibility(constraint_level level) {
- switch (level) {
- case constraint_level::none: return true;
- case constraint_level::nontrivial: return std::is_destructible_v<T>;
- case constraint_level::nothrow: return std::is_nothrow_destructible_v<T>;
- case constraint_level::trivial: return std::is_trivially_destructible_v<T>;
- default: return false;
- }
- }
- template <class T>
- class destruction_guard {
- public:
- explicit destruction_guard(T* p) noexcept : p_(p) {}
- destruction_guard(const destruction_guard&) = delete;
- ~destruction_guard() noexcept(std::is_nothrow_destructible_v<T>)
- { std::destroy_at(p_); }
- private:
- T* p_;
- };
- template <class P, qualifier_type Q, bool NE>
- struct ptr_traits : inapplicable_traits {};
- template <class P, qualifier_type Q, bool NE>
- requires(requires { *std::declval<add_qualifier_t<P, Q>>(); } &&
- (!NE || noexcept(*std::declval<add_qualifier_t<P, Q>>())))
- struct ptr_traits<P, Q, NE> : applicable_traits
- { using target_type = decltype(*std::declval<add_qualifier_t<P, Q>>()); };
- template <class D, bool NE, class R, class... Args>
- concept invocable_dispatch = (NE && std::is_nothrow_invocable_r_v<
- R, D, Args...>) || (!NE && std::is_invocable_r_v<R, D, Args...>);
- template <class D, class P, qualifier_type Q, bool NE, class R, class... Args>
- concept invocable_dispatch_ptr_indirect = ptr_traits<P, Q, NE>::applicable &&
- invocable_dispatch<
- D, NE, R, typename ptr_traits<P, Q, NE>::target_type, Args...>;
- template <class D, class P, qualifier_type Q, bool NE, class R, class... Args>
- concept invocable_dispatch_ptr_direct = invocable_dispatch<
- D, NE, R, add_qualifier_t<P, Q>, Args...> && (Q != qualifier_type::rv ||
- (NE && std::is_nothrow_destructible_v<P>) ||
- (!NE && std::is_destructible_v<P>));
- template <bool NE, class R, class... Args>
- using func_ptr_t = std::conditional_t<
- NE, R (*)(Args...) noexcept, R (*)(Args...)>;
- template <class D, class R, class... Args>
- R invoke_dispatch(Args&&... args) {
- if constexpr (std::is_void_v<R>) {
- D{}(std::forward<Args>(args)...);
- } else {
- return D{}(std::forward<Args>(args)...);
- }
- }
- template <class D, class P, qualifier_type Q, class R, class... Args>
- R indirect_conv_dispatcher(add_qualifier_t<std::byte, Q> self, Args... args)
- noexcept(invocable_dispatch_ptr_indirect<D, P, Q, true, R, Args...>) {
- return invoke_dispatch<D, R>(*std::forward<add_qualifier_t<P, Q>>(
- *std::launder(reinterpret_cast<add_qualifier_ptr_t<P, Q>>(&self))),
- std::forward<Args>(args)...);
- }
- template <class D, class P, qualifier_type Q, class R, class... Args>
- R direct_conv_dispatcher(add_qualifier_t<std::byte, Q> self, Args... args)
- noexcept(invocable_dispatch_ptr_direct<D, P, Q, true, R, Args...>) {
- auto& qp = *std::launder(reinterpret_cast<add_qualifier_ptr_t<P, Q>>(&self));
- if constexpr (Q == qualifier_type::rv) {
- destruction_guard guard{&qp};
- return invoke_dispatch<D, R>(
- std::forward<add_qualifier_t<P, Q>>(qp), std::forward<Args>(args)...);
- } else {
- return invoke_dispatch<D, R>(
- std::forward<add_qualifier_t<P, Q>>(qp), std::forward<Args>(args)...);
- }
- }
- template <class D, qualifier_type Q, class R, class... Args>
- R default_conv_dispatcher(add_qualifier_t<std::byte, Q>, Args... args)
- noexcept(invocable_dispatch<D, true, R, std::nullptr_t, Args...>)
- { return invoke_dispatch<D, R>(nullptr, std::forward<Args>(args)...); }
- template <class P>
- void copying_dispatcher(std::byte& self, const std::byte& rhs)
- noexcept(has_copyability<P>(constraint_level::nothrow)) {
- std::construct_at(reinterpret_cast<P*>(&self),
- *std::launder(reinterpret_cast<const P*>(&rhs)));
- }
- template <std::size_t Len, std::size_t Align>
- void copying_default_dispatcher(std::byte& self, const std::byte& rhs)
- noexcept {
- std::uninitialized_copy_n(
- std::assume_aligned<Align>(&rhs), Len, std::assume_aligned<Align>(&self));
- }
- template <class P>
- void relocation_dispatcher(std::byte& self, const std::byte& rhs)
- noexcept(has_relocatability<P>(constraint_level::nothrow)) {
- P* other = std::launder(reinterpret_cast<P*>(const_cast<std::byte*>(&rhs)));
- destruction_guard guard{other};
- std::construct_at(reinterpret_cast<P*>(&self), std::move(*other));
- }
- template <class P>
- void destruction_dispatcher(std::byte& self)
- noexcept(has_destructibility<P>(constraint_level::nothrow))
- { std::destroy_at(std::launder(reinterpret_cast<P*>(&self))); }
- inline void destruction_default_dispatcher(std::byte&) noexcept {}
- template <class O> struct overload_traits : inapplicable_traits {};
- template <qualifier_type Q, bool NE, class R, class... Args>
- struct overload_traits_impl : applicable_traits {
- template <bool IsDirect, class D>
- struct meta_provider {
- template <class P>
- static constexpr auto get()
- -> func_ptr_t<NE, R, add_qualifier_t<std::byte, Q>, Args...> {
- if constexpr (!IsDirect &&
- invocable_dispatch_ptr_indirect<D, P, Q, NE, R, Args...>) {
- return &indirect_conv_dispatcher<D, P, Q, R, Args...>;
- } else if constexpr (IsDirect &&
- invocable_dispatch_ptr_direct<D, P, Q, NE, R, Args...>) {
- return &direct_conv_dispatcher<D, P, Q, R, Args...>;
- } else if constexpr (invocable_dispatch<
- D, NE, R, std::nullptr_t, Args...>) {
- return &default_conv_dispatcher<D, Q, R, Args...>;
- } else {
- return nullptr;
- }
- }
- };
- using return_type = R;
- using view_type = R(Args...) const noexcept(NE);
- template <bool IsDirect, class D, class P>
- static constexpr bool applicable_ptr =
- meta_provider<IsDirect, D>::template get<P>() != nullptr;
- static constexpr qualifier_type qualifier = Q;
- };
- template <class R, class... Args>
- struct overload_traits<R(Args...)>
- : overload_traits_impl<qualifier_type::lv, false, R, Args...> {};
- template <class R, class... Args>
- struct overload_traits<R(Args...) noexcept>
- : overload_traits_impl<qualifier_type::lv, true, R, Args...> {};
- template <class R, class... Args>
- struct overload_traits<R(Args...) &>
- : overload_traits_impl<qualifier_type::lv, false, R, Args...> {};
- template <class R, class... Args>
- struct overload_traits<R(Args...) & noexcept>
- : overload_traits_impl<qualifier_type::lv, true, R, Args...> {};
- template <class R, class... Args>
- struct overload_traits<R(Args...) &&>
- : overload_traits_impl<qualifier_type::rv, false, R, Args...> {};
- template <class R, class... Args>
- struct overload_traits<R(Args...) && noexcept>
- : overload_traits_impl<qualifier_type::rv, true, R, Args...> {};
- template <class R, class... Args>
- struct overload_traits<R(Args...) const>
- : overload_traits_impl<qualifier_type::const_lv, false, R, Args...> {};
- template <class R, class... Args>
- struct overload_traits<R(Args...) const noexcept>
- : overload_traits_impl<qualifier_type::const_lv, true, R, Args...> {};
- template <class R, class... Args>
- struct overload_traits<R(Args...) const&>
- : overload_traits_impl<qualifier_type::const_lv, false, R, Args...> {};
- template <class R, class... Args>
- struct overload_traits<R(Args...) const& noexcept>
- : overload_traits_impl<qualifier_type::const_lv, true, R, Args...> {};
- template <class R, class... Args>
- struct overload_traits<R(Args...) const&&>
- : overload_traits_impl<qualifier_type::const_rv, false, R, Args...> {};
- template <class R, class... Args>
- struct overload_traits<R(Args...) const&& noexcept>
- : overload_traits_impl<qualifier_type::const_rv, true, R, Args...> {};
- template <class MP>
- struct dispatcher_meta {
- constexpr dispatcher_meta() noexcept : dispatcher(nullptr) {}
- template <class P>
- constexpr explicit dispatcher_meta(std::in_place_type_t<P>) noexcept
- : dispatcher(MP::template get<P>()) {}
- decltype(MP::template get<void>()) dispatcher;
- };
- template <class... Ms>
- struct composite_meta_impl : Ms... {
- constexpr composite_meta_impl() noexcept = default;
- template <class P>
- constexpr explicit composite_meta_impl(std::in_place_type_t<P>) noexcept
- : Ms(std::in_place_type<P>)... {}
- };
- template <class O, class I> struct meta_reduction : std::type_identity<O> {};
- template <class... Ms, class I> requires(!std::is_void_v<I>)
- struct meta_reduction<composite_meta_impl<Ms...>, I>
- : std::type_identity<composite_meta_impl<Ms..., I>> {};
- template <class... Ms1, class... Ms2>
- struct meta_reduction<composite_meta_impl<Ms1...>, composite_meta_impl<Ms2...>>
- : std::type_identity<composite_meta_impl<Ms1..., Ms2...>> {};
- template <class O, class I>
- using meta_reduction_t = typename meta_reduction<O, I>::type;
- template <class... Ms>
- using composite_meta =
- recursive_reduction_t<meta_reduction_t, composite_meta_impl<>, Ms...>;
- template <class T>
- consteval bool is_is_direct_well_formed() {
- if constexpr (requires { { T::is_direct } -> std::same_as<const bool&>; }) {
- if constexpr (is_consteval([] { return T::is_direct; })) {
- return true;
- }
- }
- return false;
- }
- template <class C, class... Os>
- struct conv_traits_impl : inapplicable_traits {};
- template <class C, class... Os>
- requires(sizeof...(Os) > 0u && (overload_traits<Os>::applicable && ...))
- struct conv_traits_impl<C, Os...> : applicable_traits {
- using meta = composite_meta_impl<dispatcher_meta<typename overload_traits<Os>
- ::template meta_provider<C::is_direct, typename C::dispatch_type>>...>;
- template <class P>
- static constexpr bool applicable_ptr =
- (overload_traits<Os>::template applicable_ptr<
- C::is_direct, typename C::dispatch_type, P> && ...);
- };
- template <class C> struct conv_traits : inapplicable_traits {};
- template <class C>
- requires(
- requires {
- typename C::dispatch_type;
- typename C::overload_types;
- } &&
- is_is_direct_well_formed<C>() &&
- std::is_trivial_v<typename C::dispatch_type> &&
- is_tuple_like_well_formed<typename C::overload_types>())
- struct conv_traits<C>
- : instantiated_t<conv_traits_impl, typename C::overload_types, C> {};
- template <class P>
- using ptr_element_t = typename std::pointer_traits<P>::element_type;
- template <bool IsDirect, class R>
- struct refl_meta {
- template <class P> requires(IsDirect)
- constexpr explicit refl_meta(std::in_place_type_t<P>)
- : reflector(std::in_place_type<P>) {}
- template <class P> requires(!IsDirect)
- constexpr explicit refl_meta(std::in_place_type_t<P>)
- : reflector(std::in_place_type<ptr_element_t<P>>) {}
- R reflector;
- };
- template <class R, class T, bool IsDirect>
- consteval bool is_reflector_well_formed() {
- if constexpr (IsDirect) {
- if constexpr (std::is_constructible_v<R, std::in_place_type_t<T>>) {
- if constexpr (is_consteval([] { return R{std::in_place_type<T>}; })) {
- return true;
- }
- }
- } else if constexpr (requires { typename ptr_element_t<T>; }) {
- return is_reflector_well_formed<R, ptr_element_t<T>, true>();
- }
- return false;
- }
- template <class R> struct refl_traits : inapplicable_traits {};
- template <class R>
- requires(requires { typename R::reflector_type; } &&
- is_is_direct_well_formed<R>())
- struct refl_traits<R> : applicable_traits {
- using meta = refl_meta<R::is_direct, typename R::reflector_type>;
- template <class P>
- static constexpr bool applicable_ptr =
- is_reflector_well_formed<typename R::reflector_type, P, R::is_direct>();
- };
- template <bool NE>
- struct copyability_meta_provider {
- template <class P>
- static constexpr func_ptr_t<NE, void, std::byte&, const std::byte&> get() {
- if constexpr (has_copyability<P>(constraint_level::trivial)) {
- return ©ing_default_dispatcher<sizeof(P), alignof(P)>;
- } else {
- return ©ing_dispatcher<P>;
- }
- }
- };
- template <bool NE>
- struct relocatability_meta_provider {
- template <class P>
- static constexpr func_ptr_t<NE, void, std::byte&, const std::byte&> get() {
- if constexpr (has_relocatability<P>(constraint_level::trivial)) {
- return ©ing_default_dispatcher<sizeof(P), alignof(P)>;
- } else {
- return &relocation_dispatcher<P>;
- }
- }
- };
- template <bool NE>
- struct destructibility_meta_provider {
- template <class P>
- static constexpr func_ptr_t<NE, void, std::byte&> get() {
- if constexpr (has_destructibility<P>(constraint_level::trivial)) {
- return &destruction_default_dispatcher;
- } else {
- return &destruction_dispatcher<P>;
- }
- }
- };
- template <template <bool> class MP, constraint_level C>
- struct lifetime_meta_traits : std::type_identity<void> {};
- template <template <bool> class MP>
- struct lifetime_meta_traits<MP, constraint_level::nothrow>
- : std::type_identity<dispatcher_meta<MP<true>>> {};
- template <template <bool> class MP>
- struct lifetime_meta_traits<MP, constraint_level::nontrivial>
- : std::type_identity<dispatcher_meta<MP<false>>> {};
- template <template <bool> class MP, constraint_level C>
- using lifetime_meta_t = typename lifetime_meta_traits<MP, C>::type;
- template <class... As>
- class ___PRO_ENFORCE_EBO composite_accessor_impl : public As... {
- template <class> friend class pro::proxy;
- template <class F> friend struct pro::proxy_indirect_accessor;
- composite_accessor_impl() noexcept = default;
- composite_accessor_impl(const composite_accessor_impl&) noexcept = default;
- composite_accessor_impl& operator=(const composite_accessor_impl&) noexcept
- = default;
- };
- template <class T>
- struct accessor_traits_impl : std::type_identity<void> {};
- template <class T>
- requires(std::is_nothrow_default_constructible_v<T> &&
- std::is_trivially_copyable_v<T> && !std::is_final_v<T>)
- struct accessor_traits_impl<T> : std::type_identity<T> {};
- template <class SFINAE, class T, class F>
- struct accessor_traits : std::type_identity<void> {};
- template <class T, class F>
- struct accessor_traits<std::void_t<typename T::template accessor<F>>, T, F>
- : accessor_traits_impl<typename T::template accessor<F>> {};
- template <class T, class F>
- using accessor_t = typename accessor_traits<void, T, F>::type;
- template <bool IsDirect, class F, class O, class I>
- struct composite_accessor_reduction : std::type_identity<O> {};
- template <bool IsDirect, class F, class... As, class I>
- requires(IsDirect == I::is_direct && !std::is_void_v<accessor_t<I, F>>)
- struct composite_accessor_reduction<
- IsDirect, F, composite_accessor_impl<As...>, I>
- : std::type_identity<composite_accessor_impl<As..., accessor_t<I, F>>> {};
- template <bool IsDirect, class F>
- struct composite_accessor_helper {
- template <class O, class I>
- using reduction_t =
- typename composite_accessor_reduction<IsDirect, F, O, I>::type;
- };
- template <bool IsDirect, class F, class... Ts>
- using composite_accessor = recursive_reduction_t<
- composite_accessor_helper<IsDirect, F>::template reduction_t,
- composite_accessor_impl<>, Ts...>;
- template <class A1, class A2> struct composite_accessor_merge_traits;
- template <class... A1, class... A2>
- struct composite_accessor_merge_traits<
- composite_accessor_impl<A1...>, composite_accessor_impl<A2...>>
- : std::type_identity<composite_accessor_impl<A1..., A2...>> {};
- template <class A1, class A2>
- using merged_composite_accessor =
- typename composite_accessor_merge_traits<A1, A2>::type;
- template <class T> struct in_place_type_traits : inapplicable_traits {};
- template <class T>
- struct in_place_type_traits<std::in_place_type_t<T>> : applicable_traits {};
- template <class T>
- constexpr bool is_in_place_type = in_place_type_traits<T>::applicable;
- template <class F>
- consteval bool is_facade_constraints_well_formed() {
- if constexpr (requires {
- { F::constraints } -> std::same_as<const proxiable_ptr_constraints&>; }) {
- if constexpr (is_consteval([] { return F::constraints; })) {
- return std::has_single_bit(F::constraints.max_align) &&
- F::constraints.max_size % F::constraints.max_align == 0u;
- }
- }
- return false;
- }
- template <class F, class... Cs>
- struct facade_conv_traits_impl : inapplicable_traits {};
- template <class F, class... Cs> requires(conv_traits<Cs>::applicable && ...)
- struct facade_conv_traits_impl<F, Cs...> : applicable_traits {
- using conv_meta = composite_meta<typename conv_traits<Cs>::meta...>;
- using conv_indirect_accessor = composite_accessor<false, F, Cs...>;
- using conv_direct_accessor = composite_accessor<true, F, Cs...>;
- template <class P>
- static constexpr bool conv_applicable_ptr =
- (conv_traits<Cs>::template applicable_ptr<P> && ...);
- template <bool IsDirect, class D, class O>
- static constexpr bool is_invocable = std::is_base_of_v<dispatcher_meta<
- typename overload_traits<O>::template meta_provider<IsDirect, D>>,
- conv_meta>;
- };
- template <class F, class... Rs>
- struct facade_refl_traits_impl : inapplicable_traits {};
- template <class F, class... Rs> requires(refl_traits<Rs>::applicable && ...)
- struct facade_refl_traits_impl<F, Rs...> : applicable_traits {
- using refl_meta = composite_meta<typename refl_traits<Rs>::meta...>;
- using refl_indirect_accessor = composite_accessor<false, F, Rs...>;
- using refl_direct_accessor = composite_accessor<true, F, Rs...>;
- template <class P>
- static constexpr bool refl_applicable_ptr =
- (refl_traits<Rs>::template applicable_ptr<P> && ...);
- };
- template <class F> struct facade_traits : inapplicable_traits {};
- template <class F>
- requires(
- requires {
- typename F::convention_types;
- typename F::reflection_types;
- } &&
- is_facade_constraints_well_formed<F>() &&
- is_tuple_like_well_formed<typename F::convention_types>() &&
- instantiated_t<facade_conv_traits_impl, typename F::convention_types, F>
- ::applicable &&
- is_tuple_like_well_formed<typename F::reflection_types>() &&
- instantiated_t<facade_refl_traits_impl, typename F::reflection_types, F>
- ::applicable)
- struct facade_traits<F>
- : instantiated_t<facade_conv_traits_impl, typename F::convention_types, F>,
- instantiated_t<facade_refl_traits_impl, typename F::reflection_types, F> {
- using copyability_meta = lifetime_meta_t<
- copyability_meta_provider, F::constraints.copyability>;
- using relocatability_meta = lifetime_meta_t<
- relocatability_meta_provider,
- F::constraints.copyability == constraint_level::trivial ?
- constraint_level::trivial : F::constraints.relocatability>;
- using destructibility_meta = lifetime_meta_t<
- destructibility_meta_provider, F::constraints.destructibility>;
- using meta = composite_meta<copyability_meta, relocatability_meta,
- destructibility_meta, typename facade_traits::conv_meta,
- typename facade_traits::refl_meta>;
- using indirect_accessor = merged_composite_accessor<
- typename facade_traits::conv_indirect_accessor,
- typename facade_traits::refl_indirect_accessor>;
- using direct_accessor = merged_composite_accessor<
- typename facade_traits::conv_direct_accessor,
- typename facade_traits::refl_direct_accessor>;
- };
- using ptr_prototype = void*[2];
- template <class M>
- struct meta_ptr_indirect_impl {
- constexpr meta_ptr_indirect_impl() noexcept : ptr_(nullptr) {};
- template <class P>
- constexpr explicit meta_ptr_indirect_impl(std::in_place_type_t<P>) noexcept
- : ptr_(&storage<P>) {}
- bool has_value() const noexcept { return ptr_ != nullptr; }
- void reset() noexcept { ptr_ = nullptr; }
- const M* operator->() const noexcept { return ptr_; }
- private:
- const M* ptr_;
- template <class P> static constexpr M storage{std::in_place_type<P>};
- };
- template <class M, class DM>
- struct meta_ptr_direct_impl : private M {
- using M::M;
- bool has_value() const noexcept { return this->DM::dispatcher != nullptr; }
- void reset() noexcept { this->DM::dispatcher = nullptr; }
- const M* operator->() const noexcept { return this; }
- };
- template <class M>
- struct meta_ptr_traits_impl : std::type_identity<meta_ptr_indirect_impl<M>> {};
- template <class MP, class... Ms>
- struct meta_ptr_traits_impl<composite_meta_impl<dispatcher_meta<MP>, Ms...>>
- : std::type_identity<meta_ptr_direct_impl<composite_meta_impl<
- dispatcher_meta<MP>, Ms...>, dispatcher_meta<MP>>> {};
- template <class M>
- struct meta_ptr_traits : std::type_identity<meta_ptr_indirect_impl<M>> {};
- template <class M>
- requires(sizeof(M) <= sizeof(ptr_prototype) &&
- alignof(M) <= alignof(ptr_prototype) &&
- std::is_nothrow_default_constructible_v<M> &&
- std::is_trivially_copyable_v<M>)
- struct meta_ptr_traits<M> : meta_ptr_traits_impl<M> {};
- template <class M>
- using meta_ptr = typename meta_ptr_traits<M>::type;
- template <class MP>
- struct meta_ptr_reset_guard {
- public:
- explicit meta_ptr_reset_guard(MP& meta) noexcept : meta_(meta) {}
- meta_ptr_reset_guard(const meta_ptr_reset_guard&) = delete;
- ~meta_ptr_reset_guard() { meta_.reset(); }
- private:
- MP& meta_;
- };
- template <class F>
- struct proxy_helper {
- static inline const auto& get_meta(const proxy<F>& p) noexcept {
- assert(p.has_value());
- return *p.meta_.operator->();
- }
- template <bool IsDirect, class D, class O, qualifier_type Q, class... Args>
- static decltype(auto) invoke(add_qualifier_t<proxy<F>, Q> p, Args&&... args) {
- auto dispatcher = get_meta(p)
- .template dispatcher_meta<typename overload_traits<O>
- ::template meta_provider<IsDirect, D>>::dispatcher;
- if constexpr (
- IsDirect && overload_traits<O>::qualifier == qualifier_type::rv) {
- meta_ptr_reset_guard guard{p.meta_};
- return dispatcher(std::forward<add_qualifier_t<std::byte, Q>>(*p.ptr_),
- std::forward<Args>(args)...);
- } else {
- return dispatcher(std::forward<add_qualifier_t<std::byte, Q>>(*p.ptr_),
- std::forward<Args>(args)...);
- }
- }
- template <class A, qualifier_type Q>
- static add_qualifier_t<proxy<F>, Q> access(add_qualifier_t<A, Q> a) {
- if constexpr (std::is_base_of_v<A, proxy<F>>) {
- return static_cast<add_qualifier_t<proxy<F>, Q>>(
- std::forward<add_qualifier_t<A, Q>>(a));
- } else {
- // Note: The use of offsetof below is technically undefined until C++20
- // because proxy may not be a standard layout type. However, all compilers
- // currently provide well-defined behavior as an extension (which is
- // demonstrated since constexpr evaluation must diagnose all undefined
- // behavior). However, various compilers also warn about this use of
- // offsetof, which must be suppressed.
- #if defined(__INTEL_COMPILER)
- #pragma warning push
- #pragma warning(disable : 1875)
- #elif defined(__GNUC__) || defined(__clang__)
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Winvalid-offsetof"
- #endif // defined(__INTEL_COMPILER)
- #if defined(__NVCC__)
- #pragma nv_diagnostic push
- #pragma nv_diag_suppress 1427
- #endif // defined(__NVCC__)
- #if defined(__NVCOMPILER)
- #pragma diagnostic push
- #pragma diag_suppress offset_in_non_POD_nonstandard
- #endif // defined(__NVCOMPILER)
- constexpr std::size_t offset = offsetof(proxy<F>, ia_);
- #if defined(__INTEL_COMPILER)
- #pragma warning pop
- #elif defined(__GNUC__) || defined(__clang__)
- #pragma GCC diagnostic pop
- #endif // defined(__INTEL_COMPILER)
- #if defined(__NVCC__)
- #pragma nv_diagnostic pop
- #endif // defined(__NVCC__)
- #if defined(__NVCOMPILER)
- #pragma diagnostic pop
- #endif // defined(__NVCOMPILER)
- return reinterpret_cast<add_qualifier_t<proxy<F>, Q>>(*(reinterpret_cast<
- add_qualifier_ptr_t<std::byte, Q>>(static_cast<add_qualifier_ptr_t<
- proxy_indirect_accessor<F>, Q>>(std::addressof(a))) - offset));
- }
- }
- };
- } // namespace details
- template <class F>
- concept facade = details::facade_traits<F>::applicable;
- template <class P, class F>
- concept proxiable = facade<F> && sizeof(P) <= F::constraints.max_size &&
- alignof(P) <= F::constraints.max_align &&
- details::has_copyability<P>(F::constraints.copyability) &&
- details::has_relocatability<P>(F::constraints.relocatability) &&
- details::has_destructibility<P>(F::constraints.destructibility) &&
- details::facade_traits<F>::template conv_applicable_ptr<P> &&
- details::facade_traits<F>::template refl_applicable_ptr<P>;
- template <class F> struct proxy_indirect_accessor {};
- template <class F> requires(!std::is_same_v<typename details::facade_traits<F>
- ::indirect_accessor, details::composite_accessor_impl<>>)
- struct proxy_indirect_accessor<F>
- : details::facade_traits<F>::indirect_accessor {};
- template <class F>
- class proxy : public details::facade_traits<F>::direct_accessor {
- static_assert(facade<F>);
- friend struct details::proxy_helper<F>;
- using _Traits = details::facade_traits<F>;
- public:
- proxy() noexcept {
- ___PRO_DEBUG(
- std::ignore = static_cast<proxy_indirect_accessor<F>*
- (proxy::*)() noexcept>(&proxy::operator->);
- std::ignore = static_cast<const proxy_indirect_accessor<F>*
- (proxy::*)() const noexcept>(&proxy::operator->);
- std::ignore = static_cast<proxy_indirect_accessor<F>&
- (proxy::*)() & noexcept>(&proxy::operator*);
- std::ignore = static_cast<const proxy_indirect_accessor<F>&
- (proxy::*)() const& noexcept>(&proxy::operator*);
- std::ignore = static_cast<proxy_indirect_accessor<F>&&
- (proxy::*)() && noexcept>(&proxy::operator*);
- std::ignore = static_cast<const proxy_indirect_accessor<F>&&
- (proxy::*)() const&& noexcept>(&proxy::operator*);
- )
- }
- proxy(std::nullptr_t) noexcept : proxy() {}
- proxy(const proxy&) noexcept requires(F::constraints.copyability ==
- constraint_level::trivial) = default;
- proxy(const proxy& rhs)
- noexcept(F::constraints.copyability == constraint_level::nothrow)
- requires(F::constraints.copyability == constraint_level::nontrivial ||
- F::constraints.copyability == constraint_level::nothrow) {
- if (rhs.meta_.has_value()) {
- rhs.meta_->_Traits::copyability_meta::dispatcher(*ptr_, *rhs.ptr_);
- meta_ = rhs.meta_;
- }
- }
- proxy(proxy&& rhs)
- noexcept(F::constraints.relocatability == constraint_level::nothrow)
- requires(F::constraints.relocatability >= constraint_level::nontrivial &&
- F::constraints.copyability != constraint_level::trivial) {
- if (rhs.meta_.has_value()) {
- details::meta_ptr_reset_guard guard{rhs.meta_};
- if constexpr (F::constraints.relocatability ==
- constraint_level::trivial) {
- std::ranges::uninitialized_copy(rhs.ptr_, ptr_);
- } else {
- rhs.meta_->_Traits::relocatability_meta::dispatcher(*ptr_, *rhs.ptr_);
- }
- meta_ = rhs.meta_;
- }
- }
- template <class P>
- proxy(P&& ptr) noexcept(std::is_nothrow_constructible_v<std::decay_t<P>, P>)
- requires(!details::is_in_place_type<std::decay_t<P>> &&
- proxiable<std::decay_t<P>, F> &&
- std::is_constructible_v<std::decay_t<P>, P>)
- : proxy() { initialize<std::decay_t<P>>(std::forward<P>(ptr)); }
- template <proxiable<F> P, class... Args>
- explicit proxy(std::in_place_type_t<P>, Args&&... args)
- noexcept(std::is_nothrow_constructible_v<P, Args...>)
- requires(std::is_constructible_v<P, Args...>)
- : proxy() { initialize<P>(std::forward<Args>(args)...); }
- template <proxiable<F> P, class U, class... Args>
- explicit proxy(std::in_place_type_t<P>, std::initializer_list<U> il,
- Args&&... args)
- noexcept(std::is_nothrow_constructible_v<
- P, std::initializer_list<U>&, Args...>)
- requires(std::is_constructible_v<P, std::initializer_list<U>&, Args...>)
- : proxy() { initialize<P>(il, std::forward<Args>(args)...); }
- proxy& operator=(std::nullptr_t)
- noexcept(F::constraints.destructibility >= constraint_level::nothrow)
- requires(F::constraints.destructibility >= constraint_level::nontrivial)
- { reset(); return *this; }
- proxy& operator=(const proxy&) noexcept requires(F::constraints.copyability ==
- constraint_level::trivial) = default;
- proxy& operator=(const proxy& rhs)
- noexcept(F::constraints.copyability >= constraint_level::nothrow &&
- F::constraints.destructibility >= constraint_level::nothrow)
- requires((F::constraints.copyability == constraint_level::nontrivial ||
- F::constraints.copyability == constraint_level::nothrow) &&
- F::constraints.destructibility >= constraint_level::nontrivial) {
- if (this != &rhs) {
- if constexpr (F::constraints.copyability == constraint_level::nothrow) {
- std::destroy_at(this);
- std::construct_at(this, rhs);
- } else {
- *this = proxy{rhs};
- }
- }
- return *this;
- }
- proxy& operator=(proxy&& rhs)
- noexcept(F::constraints.relocatability >= constraint_level::nothrow &&
- F::constraints.destructibility >= constraint_level::nothrow)
- requires(F::constraints.relocatability >= constraint_level::nontrivial &&
- F::constraints.destructibility >= constraint_level::nontrivial &&
- F::constraints.copyability != constraint_level::trivial) {
- if (this != &rhs) {
- reset();
- std::construct_at(this, std::move(rhs));
- }
- return *this;
- }
- template <class P>
- proxy& operator=(P&& ptr)
- noexcept(std::is_nothrow_constructible_v<std::decay_t<P>, P> &&
- F::constraints.destructibility >= constraint_level::nothrow)
- requires(proxiable<std::decay_t<P>, F> &&
- std::is_constructible_v<std::decay_t<P>, P> &&
- F::constraints.destructibility >= constraint_level::nontrivial) {
- if constexpr (std::is_nothrow_constructible_v<std::decay_t<P>, P>) {
- std::destroy_at(this);
- initialize<std::decay_t<P>>(std::forward<P>(ptr));
- } else {
- *this = proxy{std::forward<P>(ptr)};
- }
- return *this;
- }
- ~proxy() requires(F::constraints.destructibility == constraint_level::trivial)
- = default;
- ~proxy() noexcept(F::constraints.destructibility == constraint_level::nothrow)
- requires(F::constraints.destructibility == constraint_level::nontrivial ||
- F::constraints.destructibility == constraint_level::nothrow) {
- if (meta_.has_value())
- { meta_->_Traits::destructibility_meta::dispatcher(*ptr_); }
- }
- bool has_value() const noexcept { return meta_.has_value(); }
- explicit operator bool() const noexcept { return meta_.has_value(); }
- void reset()
- noexcept(F::constraints.destructibility >= constraint_level::nothrow)
- requires(F::constraints.destructibility >= constraint_level::nontrivial)
- { std::destroy_at(this); meta_.reset(); }
- void swap(proxy& rhs)
- noexcept(F::constraints.relocatability >= constraint_level::nothrow ||
- F::constraints.copyability == constraint_level::trivial)
- requires(F::constraints.relocatability >= constraint_level::nontrivial ||
- F::constraints.copyability == constraint_level::trivial) {
- if constexpr (F::constraints.relocatability == constraint_level::trivial ||
- F::constraints.copyability == constraint_level::trivial) {
- std::swap(meta_, rhs.meta_);
- std::swap(ptr_, rhs.ptr);
- } else {
- if (meta_.has_value()) {
- if (rhs.meta_.has_value()) {
- proxy temp = std::move(*this);
- std::construct_at(this, std::move(rhs));
- std::construct_at(&rhs, std::move(temp));
- } else {
- std::construct_at(&rhs, std::move(*this));
- }
- } else if (rhs.meta_.has_value()) {
- std::construct_at(this, std::move(rhs));
- }
- }
- }
- template <proxiable<F> P, class... Args>
- P& emplace(Args&&... args)
- noexcept(std::is_nothrow_constructible_v<P, Args...> &&
- F::constraints.destructibility >= constraint_level::nothrow)
- requires(std::is_constructible_v<P, Args...> &&
- F::constraints.destructibility >= constraint_level::nontrivial)
- { reset(); return initialize<P>(std::forward<Args>(args)...); }
- template <proxiable<F> P, class U, class... Args>
- P& emplace(std::initializer_list<U> il, Args&&... args)
- noexcept(std::is_nothrow_constructible_v<
- P, std::initializer_list<U>&, Args...> &&
- F::constraints.destructibility >= constraint_level::nothrow)
- requires(std::is_constructible_v<P, std::initializer_list<U>&, Args...> &&
- F::constraints.destructibility >= constraint_level::nontrivial)
- { reset(); return initialize<P>(il, std::forward<Args>(args)...); }
- proxy_indirect_accessor<F>* operator->() noexcept
- { return std::addressof(ia_); }
- const proxy_indirect_accessor<F>* operator->() const noexcept
- { return std::addressof(ia_); }
- proxy_indirect_accessor<F>& operator*() & noexcept { return ia_; }
- const proxy_indirect_accessor<F>& operator*() const& noexcept { return ia_; }
- proxy_indirect_accessor<F>&& operator*() && noexcept
- { return std::move(ia_); }
- const proxy_indirect_accessor<F>&& operator*() const&& noexcept
- { return std::move(ia_); }
- friend void swap(proxy& lhs, proxy& rhs) noexcept(noexcept(lhs.swap(rhs)))
- { lhs.swap(rhs); }
- friend bool operator==(const proxy& lhs, std::nullptr_t) noexcept
- { return !lhs.has_value(); }
- private:
- template <class P, class... Args>
- P& initialize(Args&&... args) {
- P& result = *std::construct_at(
- reinterpret_cast<P*>(ptr_), std::forward<Args>(args)...);
- if constexpr (std::is_constructible_v<bool, P&>) { assert(result); }
- meta_ = details::meta_ptr<typename _Traits::meta>{std::in_place_type<P>};
- return result;
- }
- [[___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE]]
- proxy_indirect_accessor<F> ia_;
- details::meta_ptr<typename _Traits::meta> meta_;
- alignas(F::constraints.max_align) std::byte ptr_[F::constraints.max_size];
- };
- template <bool IsDirect, class D, class O, class F, class... Args>
- auto proxy_invoke(proxy<F>& p, Args&&... args)
- -> typename details::overload_traits<O>::return_type {
- return details::proxy_helper<F>::template invoke<IsDirect, D, O,
- details::qualifier_type::lv>(p, std::forward<Args>(args)...);
- }
- template <bool IsDirect, class D, class O, class F, class... Args>
- auto proxy_invoke(const proxy<F>& p, Args&&... args)
- -> typename details::overload_traits<O>::return_type {
- return details::proxy_helper<F>::template invoke<IsDirect, D, O,
- details::qualifier_type::const_lv>(p, std::forward<Args>(args)...);
- }
- template <bool IsDirect, class D, class O, class F, class... Args>
- auto proxy_invoke(proxy<F>&& p, Args&&... args)
- -> typename details::overload_traits<O>::return_type {
- return details::proxy_helper<F>::template invoke<
- IsDirect, D, O, details::qualifier_type::rv>(
- std::move(p), std::forward<Args>(args)...);
- }
- template <bool IsDirect, class D, class O, class F, class... Args>
- auto proxy_invoke(const proxy<F>&& p, Args&&... args)
- -> typename details::overload_traits<O>::return_type {
- return details::proxy_helper<F>::template invoke<
- IsDirect, D, O, details::qualifier_type::const_rv>(
- std::move(p), std::forward<Args>(args)...);
- }
- template <bool IsDirect, class R, class F>
- const R& proxy_reflect(const proxy<F>& p) noexcept {
- return static_cast<const details::refl_meta<IsDirect, R>&>(
- details::proxy_helper<F>::get_meta(p)).reflector;
- }
- template <class F, class A>
- proxy<F>& access_proxy(A& a) noexcept {
- return details::proxy_helper<F>::template access<
- A, details::qualifier_type::lv>(a);
- }
- template <class F, class A>
- const proxy<F>& access_proxy(const A& a) noexcept {
- return details::proxy_helper<F>::template access<
- A, details::qualifier_type::const_lv>(a);
- }
- template <class F, class A>
- proxy<F>&& access_proxy(A&& a) noexcept {
- return details::proxy_helper<F>::template access<
- A, details::qualifier_type::rv>(std::forward<A>(a));
- }
- template <class F, class A>
- const proxy<F>&& access_proxy(const A&& a) noexcept {
- return details::proxy_helper<F>::template access<
- A, details::qualifier_type::const_rv>(std::forward<const A>(a));
- }
- namespace details {
- template <class T>
- class inplace_ptr {
- public:
- template <class... Args>
- inplace_ptr(Args&&... args)
- noexcept(std::is_nothrow_constructible_v<T, Args...>)
- requires(std::is_constructible_v<T, Args...>)
- : value_(std::forward<Args>(args)...) {}
- inplace_ptr(const inplace_ptr&)
- noexcept(std::is_nothrow_copy_constructible_v<T>) = default;
- inplace_ptr(inplace_ptr&&)
- noexcept(std::is_nothrow_move_constructible_v<T>) = default;
- T* operator->() noexcept { return &value_; }
- const T* operator->() const noexcept { return &value_; }
- T& operator*() & noexcept { return value_; }
- const T& operator*() const& noexcept { return value_; }
- T&& operator*() && noexcept { return std::forward<T>(value_); }
- const T&& operator*() const&& noexcept
- { return std::forward<const T>(value_); }
- private:
- T value_;
- };
- #if __STDC_HOSTED__
- template <class T, class Alloc>
- static auto rebind_allocator(const Alloc& alloc) {
- return typename std::allocator_traits<Alloc>::template rebind_alloc<T>(alloc);
- }
- template <class T, class Alloc, class... Args>
- static T* allocate(const Alloc& alloc, Args&&... args) {
- auto al = rebind_allocator<T>(alloc);
- auto deleter = [&](T* ptr) { al.deallocate(ptr, 1); };
- std::unique_ptr<T, decltype(deleter)> result{al.allocate(1), deleter};
- std::construct_at(result.get(), std::forward<Args>(args)...);
- return result.release();
- }
- template <class Alloc, class T>
- static void deallocate(const Alloc& alloc, T* ptr) {
- auto al = rebind_allocator<T>(alloc);
- std::destroy_at(ptr);
- al.deallocate(ptr, 1);
- }
- template <class T, class Alloc>
- class allocated_ptr {
- public:
- template <class... Args>
- allocated_ptr(const Alloc& alloc, Args&&... args)
- requires(std::is_constructible_v<T, Args...>)
- : alloc_(alloc), ptr_(allocate<T>(alloc, std::forward<Args>(args)...)) {}
- allocated_ptr(const allocated_ptr& rhs)
- requires(std::is_copy_constructible_v<T>)
- : alloc_(rhs.alloc_), ptr_(rhs.ptr_ == nullptr ? nullptr :
- allocate<T>(alloc_, std::as_const(*rhs.ptr_))) {}
- allocated_ptr(allocated_ptr&& rhs)
- noexcept(std::is_nothrow_move_constructible_v<Alloc>)
- : alloc_(std::move(rhs.alloc_)), ptr_(std::exchange(rhs.ptr_, nullptr)) {}
- ~allocated_ptr() { if (ptr_ != nullptr) { deallocate(alloc_, ptr_); } }
- T* operator->() noexcept { return ptr_; }
- const T* operator->() const noexcept { return ptr_; }
- T& operator*() & noexcept { return *ptr_; }
- const T& operator*() const& noexcept { return *ptr_; }
- T&& operator*() && noexcept { return std::forward<T>(*ptr_); }
- const T&& operator*() const&& noexcept
- { return std::forward<const T>(*ptr_); }
- private:
- [[___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE]]
- Alloc alloc_;
- T* ptr_;
- };
- template <class T, class Alloc>
- class compact_ptr {
- public:
- template <class... Args>
- compact_ptr(const Alloc& alloc, Args&&... args)
- requires(std::is_constructible_v<T, Args...>)
- : ptr_(allocate<storage>(alloc, alloc, std::forward<Args>(args)...)) {}
- compact_ptr(const compact_ptr& rhs) requires(std::is_copy_constructible_v<T>)
- : ptr_(rhs.ptr_ == nullptr ? nullptr : allocate<storage>(rhs.ptr_->alloc,
- rhs.ptr_->alloc, std::as_const(rhs.ptr_->value))) {}
- compact_ptr(compact_ptr&& rhs) noexcept
- : ptr_(std::exchange(rhs.ptr_, nullptr)) {}
- ~compact_ptr() { if (ptr_ != nullptr) { deallocate(ptr_->alloc, ptr_); } }
- T* operator->() noexcept { return &ptr_->value; }
- const T* operator->() const noexcept { return &ptr_->value; }
- T& operator*() & noexcept { return ptr_->value; }
- const T& operator*() const& noexcept { return ptr_->value; }
- T&& operator*() && noexcept { return std::forward<T>(ptr_->value); }
- const T&& operator*() const&& noexcept
- { return std::forward<const T>(ptr_->value); }
- private:
- struct storage {
- template <class... Args>
- explicit storage(const Alloc& alloc, Args&&... args)
- : value(std::forward<Args>(args)...), alloc(alloc) {}
- T value;
- Alloc alloc;
- };
- storage* ptr_;
- };
- template <class F, class T, class Alloc, class... Args>
- proxy<F> allocate_proxy_impl(const Alloc& alloc, Args&&... args) {
- if constexpr (proxiable<allocated_ptr<T, Alloc>, F>) {
- return proxy<F>{std::in_place_type<allocated_ptr<T, Alloc>>,
- alloc, std::forward<Args>(args)...};
- } else {
- return proxy<F>{std::in_place_type<compact_ptr<T, Alloc>>,
- alloc, std::forward<Args>(args)...};
- }
- }
- template <class F, class T, class... Args>
- proxy<F> make_proxy_impl(Args&&... args) {
- if constexpr (proxiable<inplace_ptr<T>, F>) {
- return proxy<F>{std::in_place_type<inplace_ptr<T>>,
- std::forward<Args>(args)...};
- } else {
- return allocate_proxy_impl<F, T>(
- std::allocator<T>{}, std::forward<Args>(args)...);
- }
- }
- #endif // __STDC_HOSTED__
- } // namespace details
- template <class T, class F>
- concept inplace_proxiable_target = proxiable<details::inplace_ptr<T>, F>;
- template <facade F, inplace_proxiable_target<F> T, class... Args>
- proxy<F> make_proxy_inplace(Args&&... args)
- noexcept(std::is_nothrow_constructible_v<T, Args...>) {
- return proxy<F>{std::in_place_type<details::inplace_ptr<T>>,
- std::forward<Args>(args)...};
- }
- template <facade F, inplace_proxiable_target<F> T, class U, class... Args>
- proxy<F> make_proxy_inplace(std::initializer_list<U> il, Args&&... args)
- noexcept(std::is_nothrow_constructible_v<
- T, std::initializer_list<U>&, Args...>) {
- return proxy<F>{std::in_place_type<details::inplace_ptr<T>>,
- il, std::forward<Args>(args)...};
- }
- template <facade F, class T>
- proxy<F> make_proxy_inplace(T&& value)
- noexcept(std::is_nothrow_constructible_v<std::decay_t<T>, T>)
- requires(inplace_proxiable_target<std::decay_t<T>, F>) {
- return proxy<F>{std::in_place_type<details::inplace_ptr<std::decay_t<T>>>,
- std::forward<T>(value)};
- }
- #if __STDC_HOSTED__
- template <facade F, class T, class Alloc, class... Args>
- proxy<F> allocate_proxy(const Alloc& alloc, Args&&... args) {
- return details::allocate_proxy_impl<F, T>(alloc, std::forward<Args>(args)...);
- }
- template <facade F, class T, class Alloc, class U, class... Args>
- proxy<F> allocate_proxy(const Alloc& alloc, std::initializer_list<U> il,
- Args&&... args) {
- return details::allocate_proxy_impl<F, T>(
- alloc, il, std::forward<Args>(args)...);
- }
- template <facade F, class Alloc, class T>
- proxy<F> allocate_proxy(const Alloc& alloc, T&& value) {
- return details::allocate_proxy_impl<F, std::decay_t<T>>(
- alloc, std::forward<T>(value));
- }
- template <facade F, class T, class... Args>
- proxy<F> make_proxy(Args&&... args)
- { return details::make_proxy_impl<F, T>(std::forward<Args>(args)...); }
- template <facade F, class T, class U, class... Args>
- proxy<F> make_proxy(std::initializer_list<U> il, Args&&... args)
- { return details::make_proxy_impl<F, T>(il, std::forward<Args>(args)...); }
- template <facade F, class T>
- proxy<F> make_proxy(T&& value) {
- return details::make_proxy_impl<F, std::decay_t<T>>(std::forward<T>(value));
- }
- #endif // __STDC_HOSTED__
- template <class F>
- struct observer_facade;
- template <class F>
- using proxy_view = proxy<observer_facade<F>>;
- #define ___PRO_DIRECT_FUNC_IMPL(...) \
- noexcept(noexcept(__VA_ARGS__)) requires(requires { __VA_ARGS__; }) \
- { return __VA_ARGS__; }
- #define ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(__MACRO, ...) \
- template <class __F, bool __IsDirect, class __D, class... __Os> \
- struct ___PRO_ENFORCE_EBO accessor { accessor() = delete; }; \
- template <class __F, bool __IsDirect, class __D, class... __Os> \
- requires(sizeof...(__Os) > 1u && (::std::is_constructible_v< \
- accessor<__F, __IsDirect, __D, __Os>> && ...)) \
- struct accessor<__F, __IsDirect, __D, __Os...> \
- : accessor<__F, __IsDirect, __D, __Os>... \
- { using accessor<__F, __IsDirect, __D, __Os>::__VA_ARGS__...; }; \
- __MACRO(, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
- __MACRO(noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
- __MACRO(&, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
- __MACRO(& noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
- __MACRO(&&, ::pro::access_proxy<__F>(::std::move(*this)), __VA_ARGS__); \
- __MACRO(&& noexcept, ::pro::access_proxy<__F>(::std::move(*this)), \
- __VA_ARGS__); \
- __MACRO(const, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
- __MACRO(const noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
- __MACRO(const&, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
- __MACRO(const& noexcept, ::pro::access_proxy<__F>(*this), __VA_ARGS__); \
- __MACRO(const&&, ::pro::access_proxy<__F>(::std::move(*this)), \
- __VA_ARGS__); \
- __MACRO(const&& noexcept, ::pro::access_proxy<__F>(::std::move(*this)), \
- __VA_ARGS__);
- #define ___PRO_ADL_ARG ::pro::details::adl_accessor_arg_t<__F, __IsDirect>
- #define ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(__MACRO, ...) \
- template <class __F, bool __IsDirect, class __D, class... __Os> \
- struct ___PRO_ENFORCE_EBO accessor { accessor() = delete; }; \
- template <class __F, bool __IsDirect, class __D, class... __Os> \
- requires(sizeof...(__Os) > 1u && (::std::is_constructible_v< \
- accessor<__F, __IsDirect, __D, __Os>> && ...)) \
- struct accessor<__F, __IsDirect, __D, __Os...> \
- : accessor<__F, __IsDirect, __D, __Os>... {}; \
- __MACRO(,, ___PRO_ADL_ARG& __self, ::pro::access_proxy<__F>(__self), \
- __VA_ARGS__); \
- __MACRO(noexcept, noexcept, ___PRO_ADL_ARG& __self, \
- ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
- __MACRO(&,, ___PRO_ADL_ARG& __self, ::pro::access_proxy<__F>(__self), \
- __VA_ARGS__); \
- __MACRO(& noexcept, noexcept, ___PRO_ADL_ARG& __self, \
- ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
- __MACRO(&&,, ___PRO_ADL_ARG&& __self, ::pro::access_proxy<__F>( \
- ::std::forward<decltype(__self)>(__self)), __VA_ARGS__); \
- __MACRO(&& noexcept, noexcept, ___PRO_ADL_ARG&& __self, \
- ::pro::access_proxy<__F>(::std::forward<decltype(__self)>(__self)), \
- __VA_ARGS__); \
- __MACRO(const,, const ___PRO_ADL_ARG& __self, \
- ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
- __MACRO(const noexcept, noexcept, const ___PRO_ADL_ARG& __self, \
- ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
- __MACRO(const&,, const ___PRO_ADL_ARG& __self, \
- ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
- __MACRO(const& noexcept, noexcept, const ___PRO_ADL_ARG& __self, \
- ::pro::access_proxy<__F>(__self), __VA_ARGS__); \
- __MACRO(const&&,, const ___PRO_ADL_ARG&& __self, ::pro::access_proxy<__F>( \
- ::std::forward<decltype(__self)>(__self)), __VA_ARGS__); \
- __MACRO(const&& noexcept, noexcept, const ___PRO_ADL_ARG&& __self, \
- ::pro::access_proxy<__F>(::std::forward<decltype(__self)>(__self)), \
- __VA_ARGS__);
- #define ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(...) \
- ___PRO_DEBUG( \
- accessor() noexcept { ::std::ignore = &accessor::__VA_ARGS__; })
- #ifdef __cpp_rtti
- class bad_proxy_cast : public std::bad_cast {
- public:
- char const* what() const noexcept override { return "pro::bad_proxy_cast"; }
- };
- #endif // __cpp_rtti
- namespace details {
- template <class F, bool IsDirect>
- using adl_accessor_arg_t =
- std::conditional_t<IsDirect, proxy<F>, proxy_indirect_accessor<F>>;
- #define ___PRO_DEF_CAST_ACCESSOR(Q, SELF, ...) \
- template <class __F, bool __IsDirect, class __D, class T> \
- struct accessor<__F, __IsDirect, __D, T() Q> { \
- ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(operator T) \
- explicit(Expl) operator T() Q { \
- if constexpr (Nullable) { \
- if (!SELF.has_value()) { return nullptr; } \
- } \
- return proxy_invoke<__IsDirect, __D, T() Q>(SELF); \
- } \
- }
- template <bool Expl, bool Nullable>
- struct cast_dispatch_base {
- ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_CAST_ACCESSOR,
- operator typename overload_traits<__Os>::return_type)
- };
- #undef ___PRO_DEF_CAST_ACCESSOR
- struct upward_conversion_dispatch : cast_dispatch_base<false, true> {
- template <class T>
- T&& operator()(T&& self) const noexcept { return std::forward<T>(self); }
- };
- template <class T>
- struct explicit_conversion_adapter {
- explicit explicit_conversion_adapter(T&& value) noexcept
- : value_(std::forward<T>(value)) {}
- explicit_conversion_adapter(const explicit_conversion_adapter&) = delete;
- template <class U>
- operator U() const noexcept(std::is_nothrow_constructible_v<U, T>)
- requires(std::is_constructible_v<U, T>)
- { return U{std::forward<T>(value_)}; }
- private:
- T&& value_;
- };
- constexpr std::size_t invalid_size = std::numeric_limits<std::size_t>::max();
- constexpr constraint_level invalid_cl = static_cast<constraint_level>(
- std::numeric_limits<std::underlying_type_t<constraint_level>>::min());
- consteval auto normalize(proxiable_ptr_constraints value) {
- if (value.max_size == invalid_size)
- { value.max_size = sizeof(ptr_prototype); }
- if (value.max_align == invalid_size)
- { value.max_align = alignof(ptr_prototype); }
- if (value.copyability == invalid_cl)
- { value.copyability = constraint_level::none; }
- if (value.relocatability == invalid_cl)
- { value.relocatability = constraint_level::nothrow; }
- if (value.destructibility == invalid_cl)
- { value.destructibility = constraint_level::nothrow; }
- return value;
- }
- consteval auto make_restricted_layout(proxiable_ptr_constraints value,
- std::size_t max_size, std::size_t max_align) {
- if (value.max_size > max_size) { value.max_size = max_size; }
- if (value.max_align > max_align) { value.max_align = max_align; }
- return value;
- }
- consteval auto make_copyable(proxiable_ptr_constraints value,
- constraint_level cl) {
- if (value.copyability < cl) { value.copyability = cl; }
- return value;
- }
- consteval auto make_relocatable(proxiable_ptr_constraints value,
- constraint_level cl) {
- if (value.relocatability < cl) { value.relocatability = cl; }
- return value;
- }
- consteval auto make_destructible(proxiable_ptr_constraints value,
- constraint_level cl) {
- if (value.destructibility < cl) { value.destructibility = cl; }
- return value;
- }
- consteval auto merge_constraints(proxiable_ptr_constraints a,
- proxiable_ptr_constraints b) {
- a = make_restricted_layout(a, b.max_size, b.max_align);
- a = make_copyable(a, b.copyability);
- a = make_relocatable(a, b.relocatability);
- a = make_destructible(a, b.destructibility);
- return a;
- }
- consteval std::size_t max_align_of(std::size_t value) {
- value &= ~value + 1u;
- return value < alignof(std::max_align_t) ? value : alignof(std::max_align_t);
- }
- template <class SFINAE, class T, class F, bool IsDirect, class... Args>
- struct accessor_instantiation_traits : std::type_identity<void> {};
- template <class T, class F, bool IsDirect, class... Args>
- struct accessor_instantiation_traits<std::void_t<typename T::template accessor<
- F, IsDirect, T, Args...>>, T, F, IsDirect, Args...>
- : std::type_identity<typename T::template accessor<
- F, IsDirect, T, Args...>> {};
- template <class T, class F, bool IsDirect, class... Args>
- using instantiated_accessor_t =
- typename accessor_instantiation_traits<void, T, F, IsDirect, Args...>::type;
- template <bool IsDirect, class D, class... Os>
- struct conv_impl {
- static constexpr bool is_direct = IsDirect;
- using dispatch_type = D;
- using overload_types = std::tuple<Os...>;
- template <class F>
- using accessor = instantiated_accessor_t<D, F, IsDirect, Os...>;
- };
- template <bool IsDirect, class R>
- struct refl_impl {
- static constexpr bool is_direct = IsDirect;
- using reflector_type = R;
- template <class F>
- using accessor = instantiated_accessor_t<R, F, IsDirect>;
- };
- template <class Cs, class Rs, proxiable_ptr_constraints C>
- struct facade_impl {
- using convention_types = Cs;
- using reflection_types = Rs;
- static constexpr proxiable_ptr_constraints constraints = C;
- };
- template <class O, class I>
- struct add_tuple_reduction : std::type_identity<O> {};
- template <class... Os, class I> requires(!std::is_same_v<I, Os> && ...)
- struct add_tuple_reduction<std::tuple<Os...>, I>
- : std::type_identity<std::tuple<Os..., I>> {};
- template <class T, class U>
- using add_tuple_t = typename add_tuple_reduction<T, U>::type;
- template <class O, class... Is>
- using merge_tuple_impl_t = recursive_reduction_t<add_tuple_t, O, Is...>;
- template <class T, class U>
- using merge_tuple_t = instantiated_t<merge_tuple_impl_t, U, T>;
- template <bool IsDirect, class D>
- struct merge_conv_traits
- { template <class... Os> using type = conv_impl<IsDirect, D, Os...>; };
- template <class C1, class C2>
- using merge_conv_t = instantiated_t<
- merge_conv_traits<C1::is_direct, typename C1::dispatch_type>::template type,
- merge_tuple_t<typename C1::overload_types, typename C2::overload_types>>;
- template <class Cs1, class C2, class C> struct add_conv_reduction;
- template <class... Cs1, class C2, class... Cs3, class C>
- struct add_conv_reduction<std::tuple<Cs1...>, std::tuple<C2, Cs3...>, C>
- : add_conv_reduction<std::tuple<Cs1..., C2>, std::tuple<Cs3...>, C> {};
- template <class... Cs1, class C2, class... Cs3, class C>
- requires(C::is_direct == C2::is_direct && std::is_same_v<
- typename C::dispatch_type, typename C2::dispatch_type>)
- struct add_conv_reduction<std::tuple<Cs1...>, std::tuple<C2, Cs3...>, C>
- : std::type_identity<std::tuple<Cs1..., merge_conv_t<C2, C>, Cs3...>> {};
- template <class... Cs, class C>
- struct add_conv_reduction<std::tuple<Cs...>, std::tuple<>, C>
- : std::type_identity<std::tuple<Cs..., merge_conv_t<
- conv_impl<C::is_direct, typename C::dispatch_type>, C>>> {};
- template <class Cs, class C>
- using add_conv_t = typename add_conv_reduction<std::tuple<>, Cs, C>::type;
- template <class F, constraint_level CL>
- using copy_conversion_overload =
- proxy<F>() const& noexcept(CL >= constraint_level::nothrow);
- template <class F, constraint_level CL>
- using move_conversion_overload =
- proxy<F>() && noexcept(CL >= constraint_level::nothrow);
- template <class Cs, class F, constraint_level CCL, constraint_level RCL>
- struct add_upward_conversion_conv
- : std::type_identity<add_conv_t<Cs, conv_impl<true,
- upward_conversion_dispatch, copy_conversion_overload<F, CCL>,
- move_conversion_overload<F, RCL>>>> {};
- template <class Cs, class F, constraint_level RCL>
- struct add_upward_conversion_conv<Cs, F, constraint_level::none, RCL>
- : std::type_identity<add_conv_t<Cs, conv_impl<true,
- upward_conversion_dispatch, move_conversion_overload<F, RCL>>>> {};
- template <class Cs, class F, constraint_level CCL>
- struct add_upward_conversion_conv<Cs, F, CCL, constraint_level::none>
- : std::type_identity<add_conv_t<Cs, conv_impl<true,
- upward_conversion_dispatch, copy_conversion_overload<F, CCL>>>> {};
- template <class Cs, class F>
- struct add_upward_conversion_conv<
- Cs, F, constraint_level::none, constraint_level::none>
- : std::type_identity<Cs> {};
- template <class Cs1, class... Cs2>
- using merge_conv_tuple_t = recursive_reduction_t<add_conv_t, Cs1, Cs2...>;
- template <class Cs, class F, bool WithUpwardConversion>
- using merge_facade_conv_t = typename add_upward_conversion_conv<
- instantiated_t<merge_conv_tuple_t, typename F::convention_types, Cs>, F,
- WithUpwardConversion ? F::constraints.copyability : constraint_level::none,
- (WithUpwardConversion &&
- F::constraints.copyability != constraint_level::trivial) ?
- F::constraints.relocatability : constraint_level::none>::type;
- struct proxy_view_dispatch : cast_dispatch_base<false, true> {
- template <class T>
- auto* operator()(T&& value) const
- ___PRO_DIRECT_FUNC_IMPL(std::addressof(*std::forward<T>(value)))
- };
- template <class P> struct facade_of_traits;
- template <class F>
- struct facade_of_traits<proxy<F>> : std::type_identity<F> {};
- template <class P> using facade_of_t = typename facade_of_traits<P>::type;
- template <class F, bool IsDirect, class D, class O>
- struct observer_overload_mapping_traits_impl
- : std::type_identity<typename overload_traits<O>::view_type> {};
- template <class F, class D, class O>
- requires(!std::is_same_v<D, proxy_view_dispatch> ||
- std::is_same_v<typename overload_traits<O>::return_type, proxy_view<F>>)
- struct observer_overload_mapping_traits_impl<F, true, D, O>
- : std::type_identity<void> {};
- template <class F, bool IsDirect, class D, class O>
- struct observer_overload_mapping_traits : std::type_identity<void> {};
- template <class F, bool IsDirect, class D, class O>
- requires(overload_traits<O>::qualifier ==
- (std::is_const_v<F> ? qualifier_type::const_lv : qualifier_type::lv))
- struct observer_overload_mapping_traits<F, IsDirect, D, O>
- : observer_overload_mapping_traits_impl<F, IsDirect, D, O> {};
- template <class F, class O>
- struct observer_overload_mapping_traits<F, true, upward_conversion_dispatch, O>
- : std::type_identity<proxy_view<std::conditional_t<std::is_const_v<F>,
- const facade_of_t<typename overload_traits<O>::return_type>,
- facade_of_t<typename overload_traits<O>::return_type>>>()
- const noexcept> {};
- template <class D>
- struct observer_dispatch_reduction : std::type_identity<D> {};
- template <>
- struct observer_dispatch_reduction<upward_conversion_dispatch>
- : std::type_identity<proxy_view_dispatch> {};
- template <class O, class I>
- struct observer_overload_ignore_void_reduction : std::type_identity<O> {};
- template <bool IsDirect, class D, class... Os, class O>
- requires(!std::is_void_v<O>)
- struct observer_overload_ignore_void_reduction<conv_impl<IsDirect, D, Os...>, O>
- : std::type_identity<conv_impl<IsDirect, D, Os..., O>> {};
- template <class O, class I>
- using observer_overload_ignore_void_reduction_t =
- typename observer_overload_ignore_void_reduction<O, I>::type;
- template <class F, class C, class... Os>
- using observer_conv_impl = recursive_reduction_t<
- observer_overload_ignore_void_reduction_t,
- conv_impl<C::is_direct, typename observer_dispatch_reduction<
- typename C::dispatch_type>::type>,
- typename observer_overload_mapping_traits<
- F, C::is_direct, typename C::dispatch_type, Os>::type...>;
- template <class O, class I>
- struct observer_conv_reduction : std::type_identity<O> {};
- template <class O, class I>
- requires(std::tuple_size_v<typename I::overload_types> != 0u)
- struct observer_conv_reduction<O, I> : std::type_identity<add_conv_t<O, I>> {};
- template <class F>
- struct observer_conv_reduction_traits {
- template <class O, class I>
- using type = typename observer_conv_reduction<O, instantiated_t<
- observer_conv_impl, typename I::overload_types, F, I>>::type;
- };
- template <class O, class I>
- struct observer_refl_reduction : std::type_identity<O> {};
- template <class... Rs, class R> requires(!R::is_direct)
- struct observer_refl_reduction<std::tuple<Rs...>, R>
- : std::type_identity<std::tuple<Rs..., R>> {};
- template <class O, class I>
- using observer_refl_reduction_t = typename observer_refl_reduction<O, I>::type;
- template <class F, class... Cs>
- struct observer_facade_conv_impl {
- using convention_types = recursive_reduction_t<
- observer_conv_reduction_traits<F>::template type, std::tuple<>, Cs...>;
- };
- template <class... Rs>
- struct observer_facade_refl_impl {
- using reflection_types = recursive_reduction_t<
- observer_refl_reduction_t, std::tuple<>, Rs...>;
- };
- template <class F>
- struct proxy_view_overload_traits
- : std::type_identity<proxy_view<F>() noexcept> {};
- template <class F>
- struct proxy_view_overload_traits<const F>
- : std::type_identity<proxy_view<const F>() const noexcept> {};
- template <class F>
- using proxy_view_overload = typename proxy_view_overload_traits<F>::type;
- template <std::size_t N>
- struct sign {
- consteval sign(const char (&str)[N])
- { for (std::size_t i = 0; i < N; ++i) { value[i] = str[i]; } }
- char value[N];
- };
- template <std::size_t N>
- sign(const char (&str)[N]) -> sign<N>;
- #if __STDC_HOSTED__
- template <class CharT> struct format_overload_traits;
- template <>
- struct format_overload_traits<char>
- : std::type_identity<std::format_context::iterator(
- std::string_view spec, std::format_context& fc) const> {};
- template <>
- struct format_overload_traits<wchar_t>
- : std::type_identity<std::wformat_context::iterator(
- std::wstring_view spec, std::wformat_context& fc) const> {};
- template <class CharT>
- using format_overload_t = typename format_overload_traits<CharT>::type;
- struct format_dispatch {
- // Note: This function requires std::formatter<T, CharT> to be well-formed.
- // However, the standard did not provide such facility before C++23. In the
- // "required" clause of this function, std::formattable (C++23) is preferred
- // when available. Otherwise, when building with C++20, we simply check
- // whether std::formatter<T, CharT> is a disabled specialization of
- // std::formatter by std::is_default_constructible_v as per
- // [format.formatter.spec].
- template <class T, class CharT, class OutIt>
- OutIt operator()(const T& self, std::basic_string_view<CharT> spec,
- std::basic_format_context<OutIt, CharT>& fc) const
- requires(
- #if defined(__cpp_lib_format_ranges) && __cpp_lib_format_ranges >= 202207L
- std::formattable<T, CharT>
- #else
- std::is_default_constructible_v<std::formatter<T, CharT>>
- #endif // defined(__cpp_lib_format_ranges) && __cpp_lib_format_ranges >= 202207L
- ) {
- std::formatter<T, CharT> impl;
- {
- std::basic_format_parse_context<CharT> pc{spec};
- impl.parse(pc);
- }
- return impl.format(self, fc);
- }
- };
- #endif // __STDC_HOSTED__
- #ifdef __cpp_rtti
- struct proxy_cast_context {
- const std::type_info* type_ptr;
- bool is_ref;
- bool is_const;
- void* result_ptr;
- };
- struct proxy_cast_dispatch;
- template <class F, bool IsDirect, class D, class O>
- struct proxy_cast_accessor_impl {
- using _Self = add_qualifier_t<
- adl_accessor_arg_t<F, IsDirect>, overload_traits<O>::qualifier>;
- template <class T>
- friend T proxy_cast(_Self self) {
- static_assert(!std::is_rvalue_reference_v<T>);
- if (!access_proxy<F>(self).has_value()) { ___PRO_THROW(bad_proxy_cast{}); }
- if constexpr (std::is_lvalue_reference_v<T>) {
- using U = std::remove_reference_t<T>;
- void* result = nullptr;
- proxy_cast_context ctx{.type_ptr = &typeid(T), .is_ref = true,
- .is_const = std::is_const_v<U>, .result_ptr = &result};
- proxy_invoke<IsDirect, D, O>(
- access_proxy<F>(std::forward<_Self>(self)), ctx);
- if (result == nullptr) { ___PRO_THROW(bad_proxy_cast{}); }
- return *static_cast<U*>(result);
- } else {
- std::optional<std::remove_const_t<T>> result;
- proxy_cast_context ctx{.type_ptr = &typeid(T), .is_ref = false,
- .is_const = false, .result_ptr = &result};
- proxy_invoke<IsDirect, D, O>(
- access_proxy<F>(std::forward<_Self>(self)), ctx);
- if (!result.has_value()) { ___PRO_THROW(bad_proxy_cast{}); }
- return std::move(*result);
- }
- }
- template <class T>
- friend T* proxy_cast(std::remove_reference_t<_Self>* self) noexcept
- requires(std::is_lvalue_reference_v<_Self>) {
- if (!access_proxy<F>(*self).has_value()) { return nullptr; }
- void* result = nullptr;
- proxy_cast_context ctx{.type_ptr = &typeid(T), .is_ref = true,
- .is_const = std::is_const_v<T>, .result_ptr = &result};
- proxy_invoke<IsDirect, D, O>(access_proxy<F>(*self), ctx);
- return static_cast<T*>(result);
- }
- };
- #define ___PRO_DEF_PROXY_CAST_ACCESSOR(Q, ...) \
- template <class F, bool IsDirect, class D> \
- struct accessor<F, IsDirect, D, void(proxy_cast_context) Q> \
- : proxy_cast_accessor_impl<F, IsDirect, D, \
- void(proxy_cast_context) Q> {}
- struct proxy_cast_dispatch {
- template <class T>
- void operator()(T&& self, proxy_cast_context ctx) const {
- if (typeid(T) == *ctx.type_ptr) {
- if (ctx.is_ref) {
- if constexpr (std::is_lvalue_reference_v<T>) {
- if (ctx.is_const || !std::is_const_v<T>) {
- *static_cast<void**>(ctx.result_ptr) = (void*)&self;
- }
- }
- } else {
- if constexpr (std::is_constructible_v<std::decay_t<T>, T>) {
- static_cast<std::optional<std::decay_t<T>>*>(ctx.result_ptr)
- ->emplace(std::forward<T>(self));
- }
- }
- }
- }
- ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_PROXY_CAST_ACCESSOR)
- };
- #undef ___PRO_DEF_PROXY_CAST_ACCESSOR
- struct proxy_typeid_reflector {
- template <class T>
- constexpr explicit proxy_typeid_reflector(std::in_place_type_t<T>)
- : info(&typeid(T)) {}
- constexpr proxy_typeid_reflector(const proxy_typeid_reflector&) = default;
- template <class F, bool IsDirect, class R>
- struct accessor {
- friend const std::type_info& proxy_typeid(
- const adl_accessor_arg_t<F, IsDirect>& self) noexcept {
- const proxy<F>& p = access_proxy<F>(self);
- if (!p.has_value()) { return typeid(void); }
- const proxy_typeid_reflector& refl = proxy_reflect<IsDirect, R>(p);
- return *refl.info;
- }
- ___PRO_DEBUG(
- accessor() noexcept { std::ignore = &accessor::_symbol_guard; }
- private:
- static inline const std::type_info& _symbol_guard(
- const adl_accessor_arg_t<F, IsDirect>& self) noexcept
- { return proxy_typeid(self); }
- )
- };
- const std::type_info* info;
- };
- #endif // __cpp_rtti
- struct wildcard {
- wildcard() = delete;
- template <class T>
- [[noreturn]] operator T() const {
- #ifdef __cpp_lib_unreachable
- std::unreachable();
- #else
- std::abort();
- #endif // __cpp_lib_unreachable
- }
- };
- } // namespace details
- template <class Cs, class Rs, proxiable_ptr_constraints C>
- struct basic_facade_builder {
- template <class D, class... Os>
- requires(sizeof...(Os) > 0u &&
- (details::overload_traits<Os>::applicable && ...))
- using add_indirect_convention = basic_facade_builder<details::add_conv_t<
- Cs, details::conv_impl<false, D, Os...>>, Rs, C>;
- template <class D, class... Os>
- requires(sizeof...(Os) > 0u &&
- (details::overload_traits<Os>::applicable && ...))
- using add_direct_convention = basic_facade_builder<details::add_conv_t<
- Cs, details::conv_impl<true, D, Os...>>, Rs, C>;
- template <class D, class... Os>
- requires(sizeof...(Os) > 0u &&
- (details::overload_traits<Os>::applicable && ...))
- using add_convention = add_indirect_convention<D, Os...>;
- template <class R>
- using add_indirect_reflection = basic_facade_builder<
- Cs, details::add_tuple_t<Rs, details::refl_impl<false, R>>, C>;
- template <class R>
- using add_direct_reflection = basic_facade_builder<
- Cs, details::add_tuple_t<Rs, details::refl_impl<true, R>>, C>;
- template <class R>
- using add_reflection = add_indirect_reflection<R>;
- template <facade F, bool WithUpwardConversion = false>
- using add_facade = basic_facade_builder<
- details::merge_facade_conv_t<Cs, F, WithUpwardConversion>,
- details::merge_tuple_t<Rs, typename F::reflection_types>,
- details::merge_constraints(C, F::constraints)>;
- template <std::size_t PtrSize,
- std::size_t PtrAlign = details::max_align_of(PtrSize)>
- requires(std::has_single_bit(PtrAlign) && PtrSize % PtrAlign == 0u)
- using restrict_layout = basic_facade_builder<
- Cs, Rs, details::make_restricted_layout(C, PtrSize, PtrAlign)>;
- template <constraint_level CL>
- using support_copy = basic_facade_builder<
- Cs, Rs, details::make_copyable(C, CL)>;
- template <constraint_level CL>
- using support_relocation = basic_facade_builder<
- Cs, Rs, details::make_relocatable(C, CL)>;
- template <constraint_level CL>
- using support_destruction = basic_facade_builder<
- Cs, Rs, details::make_destructible(C, CL)>;
- #if __STDC_HOSTED__
- using support_format = add_convention<
- details::format_dispatch, details::format_overload_t<char>>;
- using support_wformat = add_convention<
- details::format_dispatch, details::format_overload_t<wchar_t>>;
- #endif // __STDC_HOSTED__
- #ifdef __cpp_rtti
- using support_indirect_rtti = basic_facade_builder<
- details::add_conv_t<Cs, details::conv_impl<false,
- details::proxy_cast_dispatch, void(details::proxy_cast_context) &,
- void(details::proxy_cast_context) const&,
- void(details::proxy_cast_context) &&>>,
- details::add_tuple_t<Rs, details::refl_impl<false,
- details::proxy_typeid_reflector>>, C>;
- using support_direct_rtti = basic_facade_builder<
- details::add_conv_t<Cs, details::conv_impl<true,
- details::proxy_cast_dispatch, void(details::proxy_cast_context) &,
- void(details::proxy_cast_context) const&,
- void(details::proxy_cast_context) &&>>,
- details::add_tuple_t<Rs, details::refl_impl<true,
- details::proxy_typeid_reflector>>, C>;
- using support_rtti = support_indirect_rtti;
- #endif // __cpp_rtti
- template <class F>
- using add_view = add_direct_convention<
- details::proxy_view_dispatch, details::proxy_view_overload<F>>;
- using build = details::facade_impl<Cs, Rs, details::normalize(C)>;
- basic_facade_builder() = delete;
- };
- template <class F>
- struct observer_facade
- : details::instantiated_t<details::observer_facade_conv_impl,
- typename F::convention_types, F>,
- details::instantiated_t<details::observer_facade_refl_impl,
- typename F::reflection_types> {
- static constexpr proxiable_ptr_constraints constraints{
- .max_size = sizeof(void*), .max_align = alignof(void*),
- .copyability = constraint_level::trivial,
- .relocatability = constraint_level::trivial,
- .destructibility = constraint_level::trivial};
- };
- using facade_builder = basic_facade_builder<std::tuple<>, std::tuple<>,
- proxiable_ptr_constraints{
- .max_size = details::invalid_size,
- .max_align = details::invalid_size,
- .copyability = details::invalid_cl,
- .relocatability = details::invalid_cl,
- .destructibility = details::invalid_cl}>;
- template <details::sign Sign, bool Rhs = false>
- struct operator_dispatch;
- #define ___PRO_DEF_LHS_LEFT_OP_ACCESSOR(Q, SELF, ...) \
- template <class __F, bool __IsDirect, class __D, class R> \
- struct accessor<__F, __IsDirect, __D, R() Q> { \
- ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
- R __VA_ARGS__() Q { return proxy_invoke<__IsDirect, __D, R() Q>(SELF); } \
- }
- #define ___PRO_DEF_LHS_ANY_OP_ACCESSOR(Q, SELF, ...) \
- template <class __F, bool __IsDirect, class __D, class R, class... Args> \
- struct accessor<__F, __IsDirect, __D, R(Args...) Q> { \
- ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
- R __VA_ARGS__(Args... args) Q { \
- return proxy_invoke<__IsDirect, __D, R(Args...) Q>( \
- SELF, std::forward<Args>(args)...); \
- } \
- }
- #define ___PRO_DEF_LHS_UNARY_OP_ACCESSOR ___PRO_DEF_LHS_ANY_OP_ACCESSOR
- #define ___PRO_DEF_LHS_BINARY_OP_ACCESSOR ___PRO_DEF_LHS_ANY_OP_ACCESSOR
- #define ___PRO_DEF_LHS_ALL_OP_ACCESSOR ___PRO_DEF_LHS_ANY_OP_ACCESSOR
- #define ___PRO_LHS_LEFT_OP_DISPATCH_BODY_IMPL(...) \
- template <class T> \
- decltype(auto) operator()(T&& self) const \
- ___PRO_DIRECT_FUNC_IMPL(__VA_ARGS__ std::forward<T>(self))
- #define ___PRO_LHS_UNARY_OP_DISPATCH_BODY_IMPL(...) \
- template <class T> \
- decltype(auto) operator()(T&& self) const \
- ___PRO_DIRECT_FUNC_IMPL(__VA_ARGS__ std::forward<T>(self)) \
- template <class T> \
- decltype(auto) operator()(T&& self, int) const \
- ___PRO_DIRECT_FUNC_IMPL(std::forward<T>(self) __VA_ARGS__)
- #define ___PRO_LHS_BINARY_OP_DISPATCH_BODY_IMPL(...) \
- template <class T, class Arg> \
- decltype(auto) operator()(T&& self, Arg&& arg) const \
- ___PRO_DIRECT_FUNC_IMPL( \
- std::forward<T>(self) __VA_ARGS__ std::forward<Arg>(arg))
- #define ___PRO_LHS_ALL_OP_DISPATCH_BODY_IMPL(...) \
- ___PRO_LHS_LEFT_OP_DISPATCH_BODY_IMPL(__VA_ARGS__) \
- ___PRO_LHS_BINARY_OP_DISPATCH_BODY_IMPL(__VA_ARGS__)
- #define ___PRO_LHS_OP_DISPATCH_IMPL(TYPE, ...) \
- template <> \
- struct operator_dispatch<#__VA_ARGS__, false> { \
- ___PRO_LHS_##TYPE##_OP_DISPATCH_BODY_IMPL(__VA_ARGS__) \
- ___PRO_DEF_MEM_ACCESSOR_TEMPLATE( \
- ___PRO_DEF_LHS_##TYPE##_OP_ACCESSOR, operator __VA_ARGS__) \
- };
- #define ___PRO_DEF_RHS_OP_ACCESSOR(Q, NE, SELF_ARG, SELF, ...) \
- template <class __F, bool __IsDirect, class __D, class R, class Arg> \
- struct accessor<__F, __IsDirect, __D, R(Arg) Q> { \
- friend R operator __VA_ARGS__(Arg arg, SELF_ARG) NE { \
- return proxy_invoke<__IsDirect, __D, R(Arg) Q>( \
- SELF, std::forward<Arg>(arg)); \
- } \
- ___PRO_DEBUG( \
- accessor() noexcept { std::ignore = &accessor::_symbol_guard; } \
- \
- private: \
- static inline R _symbol_guard(Arg arg, SELF_ARG) NE { \
- return std::forward<Arg>(arg) __VA_ARGS__ \
- std::forward<decltype(__self)>(__self); \
- } \
- ) \
- }
- #define ___PRO_RHS_OP_DISPATCH_IMPL(...) \
- template <> \
- struct operator_dispatch<#__VA_ARGS__, true> { \
- template <class T, class Arg> \
- decltype(auto) operator()(T&& self, Arg&& arg) const \
- ___PRO_DIRECT_FUNC_IMPL( \
- std::forward<Arg>(arg) __VA_ARGS__ std::forward<T>(self)) \
- ___PRO_DEF_FREE_ACCESSOR_TEMPLATE( \
- ___PRO_DEF_RHS_OP_ACCESSOR, __VA_ARGS__) \
- };
- #define ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL(...) \
- ___PRO_LHS_OP_DISPATCH_IMPL(ALL, __VA_ARGS__) \
- ___PRO_RHS_OP_DISPATCH_IMPL(__VA_ARGS__)
- #define ___PRO_BINARY_OP_DISPATCH_IMPL(...) \
- ___PRO_LHS_OP_DISPATCH_IMPL(BINARY, __VA_ARGS__) \
- ___PRO_RHS_OP_DISPATCH_IMPL(__VA_ARGS__)
- #define ___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR(Q, SELF, ...) \
- template <class __F, bool __IsDirect, class __D, class R, class Arg> \
- struct accessor<__F, __IsDirect, __D, R(Arg) Q> { \
- ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
- decltype(auto) __VA_ARGS__(Arg arg) Q { \
- proxy_invoke<__IsDirect, __D, R(Arg) Q>(SELF, std::forward<Arg>(arg)); \
- if constexpr (__IsDirect) { \
- return SELF; \
- } else { \
- return *SELF; \
- } \
- } \
- }
- #define ___PRO_DEF_RHS_ASSIGNMENT_OP_ACCESSOR(Q, NE, SELF_ARG, SELF, ...) \
- template <class __F, bool __IsDirect, class __D, class R, class Arg> \
- struct accessor<__F, __IsDirect, __D, R(Arg&) Q> { \
- friend Arg& operator __VA_ARGS__(Arg& arg, SELF_ARG) NE { \
- proxy_invoke<__IsDirect, __D, R(Arg&) Q>(SELF, arg); \
- return arg; \
- } \
- ___PRO_DEBUG( \
- accessor() noexcept { std::ignore = &accessor::_symbol_guard; } \
- \
- private: \
- static inline Arg& _symbol_guard(Arg& arg, SELF_ARG) NE \
- { return arg __VA_ARGS__ std::forward<decltype(__self)>(__self); } \
- ) \
- }
- #define ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(...) \
- template <> \
- struct operator_dispatch<#__VA_ARGS__, false> { \
- template <class T, class Arg> \
- decltype(auto) operator()(T&& self, Arg&& arg) const \
- ___PRO_DIRECT_FUNC_IMPL(std::forward<T>(self) __VA_ARGS__ \
- std::forward<Arg>(arg)) \
- ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR, \
- operator __VA_ARGS__) \
- }; \
- template <> \
- struct operator_dispatch<#__VA_ARGS__, true> { \
- template <class T, class Arg> \
- decltype(auto) operator()(T&& self, Arg&& arg) const \
- ___PRO_DIRECT_FUNC_IMPL( \
- std::forward<Arg>(arg) __VA_ARGS__ std::forward<T>(self)) \
- ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_RHS_ASSIGNMENT_OP_ACCESSOR, \
- __VA_ARGS__) \
- };
- ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL(+)
- ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL(-)
- ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL(*)
- ___PRO_BINARY_OP_DISPATCH_IMPL(/)
- ___PRO_BINARY_OP_DISPATCH_IMPL(%)
- ___PRO_LHS_OP_DISPATCH_IMPL(UNARY, ++)
- ___PRO_LHS_OP_DISPATCH_IMPL(UNARY, --)
- ___PRO_BINARY_OP_DISPATCH_IMPL(==)
- ___PRO_BINARY_OP_DISPATCH_IMPL(!=)
- ___PRO_BINARY_OP_DISPATCH_IMPL(>)
- ___PRO_BINARY_OP_DISPATCH_IMPL(<)
- ___PRO_BINARY_OP_DISPATCH_IMPL(>=)
- ___PRO_BINARY_OP_DISPATCH_IMPL(<=)
- ___PRO_BINARY_OP_DISPATCH_IMPL(<=>)
- ___PRO_LHS_OP_DISPATCH_IMPL(LEFT, !)
- ___PRO_BINARY_OP_DISPATCH_IMPL(&&)
- ___PRO_BINARY_OP_DISPATCH_IMPL(||)
- ___PRO_LHS_OP_DISPATCH_IMPL(LEFT, ~)
- ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL(&)
- ___PRO_BINARY_OP_DISPATCH_IMPL(|)
- ___PRO_BINARY_OP_DISPATCH_IMPL(^)
- ___PRO_BINARY_OP_DISPATCH_IMPL(<<)
- ___PRO_BINARY_OP_DISPATCH_IMPL(>>)
- ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(+=)
- ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(-=)
- ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(*=)
- ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(/=)
- ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(&=)
- ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(|=)
- ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(^=)
- ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(<<=)
- ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL(>>=)
- ___PRO_BINARY_OP_DISPATCH_IMPL(,)
- ___PRO_BINARY_OP_DISPATCH_IMPL(->*)
- template <>
- struct operator_dispatch<"()", false> {
- template <class T, class... Args>
- decltype(auto) operator()(T&& self, Args&&... args) const
- ___PRO_DIRECT_FUNC_IMPL(
- std::forward<T>(self)(std::forward<Args>(args)...))
- ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ANY_OP_ACCESSOR, operator())
- };
- template <>
- struct operator_dispatch<"[]", false> {
- #if defined(__cpp_multidimensional_subscript) && __cpp_multidimensional_subscript >= 202110L
- template <class T, class... Args>
- decltype(auto) operator()(T&& self, Args&&... args) const
- ___PRO_DIRECT_FUNC_IMPL(
- std::forward<T>(self)[std::forward<Args>(args)...])
- #else
- template <class T, class Arg>
- decltype(auto) operator()(T&& self, Arg&& arg) const
- ___PRO_DIRECT_FUNC_IMPL(std::forward<T>(self)[std::forward<Arg>(arg)])
- #endif // defined(__cpp_multidimensional_subscript) && __cpp_multidimensional_subscript >= 202110L
- ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_LHS_ANY_OP_ACCESSOR, operator[])
- };
- #undef ___PRO_ASSIGNMENT_OP_DISPATCH_IMPL
- #undef ___PRO_DEF_RHS_ASSIGNMENT_OP_ACCESSOR
- #undef ___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR
- #undef ___PRO_BINARY_OP_DISPATCH_IMPL
- #undef ___PRO_EXTENDED_BINARY_OP_DISPATCH_IMPL
- #undef ___PRO_RHS_OP_DISPATCH_IMPL
- #undef ___PRO_DEF_RHS_OP_ACCESSOR
- #undef ___PRO_LHS_OP_DISPATCH_IMPL
- #undef ___PRO_LHS_ALL_OP_DISPATCH_BODY_IMPL
- #undef ___PRO_LHS_BINARY_OP_DISPATCH_BODY_IMPL
- #undef ___PRO_LHS_UNARY_OP_DISPATCH_BODY_IMPL
- #undef ___PRO_LHS_LEFT_OP_DISPATCH_BODY_IMPL
- #undef ___PRO_DEF_LHS_ALL_OP_ACCESSOR
- #undef ___PRO_DEF_LHS_BINARY_OP_ACCESSOR
- #undef ___PRO_DEF_LHS_UNARY_OP_ACCESSOR
- #undef ___PRO_DEF_LHS_ANY_OP_ACCESSOR
- #undef ___PRO_DEF_LHS_LEFT_OP_ACCESSOR
- struct implicit_conversion_dispatch
- : details::cast_dispatch_base<false, false> {
- template <class T>
- T&& operator()(T&& self) const noexcept { return std::forward<T>(self); }
- };
- struct explicit_conversion_dispatch : details::cast_dispatch_base<true, false> {
- template <class T>
- auto operator()(T&& self) const noexcept
- { return details::explicit_conversion_adapter<T>{std::forward<T>(self)}; }
- };
- using conversion_dispatch = explicit_conversion_dispatch;
- class not_implemented : public std::exception {
- public:
- char const* what() const noexcept override { return "pro::not_implemented"; }
- };
- template <class D>
- struct weak_dispatch : D {
- using D::operator();
- template <class... Args>
- [[noreturn]] details::wildcard operator()(std::nullptr_t, Args&&...) const
- { ___PRO_THROW(not_implemented{}); }
- };
- #define ___PRO_EXPAND_IMPL(__X) __X
- #define ___PRO_EXPAND_MACRO_IMPL( \
- __MACRO, __1, __2, __3, __NAME, ...) \
- __MACRO##_##__NAME
- #define ___PRO_EXPAND_MACRO(__MACRO, ...) \
- ___PRO_EXPAND_IMPL(___PRO_EXPAND_MACRO_IMPL( \
- __MACRO, __VA_ARGS__, 3, 2)(__VA_ARGS__))
- #define ___PRO_DEF_MEM_ACCESSOR(__Q, __SELF, ...) \
- template <class __F, bool __IsDirect, class __D, class __R, \
- class... __Args> \
- struct accessor<__F, __IsDirect, __D, __R(__Args...) __Q> { \
- ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
- __R __VA_ARGS__(__Args... __args) __Q { \
- return ::pro::proxy_invoke<__IsDirect, __D, __R(__Args...) __Q>( \
- __SELF, ::std::forward<__Args>(__args)...); \
- } \
- }
- #define ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \
- struct __NAME { \
- template <class __T, class... __Args> \
- decltype(auto) operator()(__T&& __self, __Args&&... __args) const \
- ___PRO_DIRECT_FUNC_IMPL(::std::forward<__T>(__self) \
- .__FUNC(::std::forward<__Args>(__args)...)) \
- ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_MEM_ACCESSOR, __FNAME) \
- }
- #define ___PRO_DEF_MEM_DISPATCH_2(__NAME, __FUNC) \
- ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FUNC)
- #define ___PRO_DEF_MEM_DISPATCH_3(__NAME, __FUNC, __FNAME) \
- ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME)
- #define PRO_DEF_MEM_DISPATCH(__NAME, ...) \
- ___PRO_EXPAND_MACRO(___PRO_DEF_MEM_DISPATCH, __NAME, __VA_ARGS__)
- #define ___PRO_DEF_FREE_ACCESSOR(__Q, __NE, __SELF_ARG, __SELF, ...) \
- template <class __F, bool __IsDirect, class __D, class __R, \
- class... __Args> \
- struct accessor<__F, __IsDirect, __D, __R(__Args...) __Q> { \
- friend __R __VA_ARGS__(__SELF_ARG, __Args... __args) __NE { \
- return ::pro::proxy_invoke<__IsDirect, __D, __R(__Args...) __Q>( \
- __SELF, ::std::forward<__Args>(__args)...); \
- } \
- ___PRO_DEBUG( \
- accessor() noexcept { ::std::ignore = &accessor::_symbol_guard; } \
- \
- private: \
- static inline __R _symbol_guard(__SELF_ARG, __Args... __args) __NE { \
- return __VA_ARGS__(::std::forward<decltype(__self)>(__self), \
- ::std::forward<__Args>(__args)...); \
- } \
- ) \
- }
- #define ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \
- struct __NAME { \
- template <class __T, class... __Args> \
- decltype(auto) operator()(__T&& __self, __Args&&... __args) const \
- ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__T>(__self), \
- ::std::forward<__Args>(__args)...)) \
- ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(___PRO_DEF_FREE_ACCESSOR, __FNAME) \
- }
- #define ___PRO_DEF_FREE_DISPATCH_2(__NAME, __FUNC) \
- ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FUNC)
- #define ___PRO_DEF_FREE_DISPATCH_3(__NAME, __FUNC, __FNAME) \
- ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FNAME)
- #define PRO_DEF_FREE_DISPATCH(__NAME, ...) \
- ___PRO_EXPAND_MACRO(___PRO_DEF_FREE_DISPATCH, __NAME, __VA_ARGS__)
- #define ___PRO_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME) \
- struct __NAME { \
- template <class __T, class... __Args> \
- decltype(auto) operator()(__T&& __self, __Args&&... __args) const \
- ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__T>(__self), \
- ::std::forward<__Args>(__args)...)) \
- ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(___PRO_DEF_MEM_ACCESSOR, __FNAME) \
- }
- #define ___PRO_DEF_FREE_AS_MEM_DISPATCH_2(__NAME, __FUNC) \
- ___PRO_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FUNC)
- #define ___PRO_DEF_FREE_AS_MEM_DISPATCH_3(__NAME, __FUNC, __FNAME) \
- ___PRO_DEF_FREE_AS_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME)
- #define PRO_DEF_FREE_AS_MEM_DISPATCH(__NAME, ...) \
- ___PRO_EXPAND_MACRO(___PRO_DEF_FREE_AS_MEM_DISPATCH, __NAME, __VA_ARGS__)
- #define PRO_DEF_WEAK_DISPATCH(__NAME, __D, __FUNC) \
- struct [[deprecated("'PRO_DEF_WEAK_DISPATCH' is deprecated. " \
- "Use pro::weak_dispatch<" #__D "> instead.")]] __NAME : __D { \
- using __D::operator(); \
- template <class... __Args> \
- decltype(auto) operator()(::std::nullptr_t, __Args&&... __args) const \
- ___PRO_DIRECT_FUNC_IMPL(__FUNC(::std::forward<__Args>(__args)...)) \
- }
- } // namespace pro
- #if __STDC_HOSTED__
- namespace std {
- template <class F, class CharT>
- requires(pro::details::facade_traits<F>::template is_invocable<false,
- pro::details::format_dispatch, pro::details::format_overload_t<CharT>>)
- struct formatter<pro::proxy_indirect_accessor<F>, CharT> {
- constexpr auto parse(basic_format_parse_context<CharT>& pc) {
- for (auto it = pc.begin(); it != pc.end(); ++it) {
- if (*it == '}') {
- spec_ = basic_string_view<CharT>{pc.begin(), it + 1};
- return it;
- }
- }
- return pc.end();
- }
- template <class OutIt>
- OutIt format(const pro::proxy_indirect_accessor<F>& ia,
- basic_format_context<OutIt, CharT>& fc) const {
- auto& p = pro::access_proxy<F>(ia);
- if (!p.has_value()) { ___PRO_THROW(format_error{"null proxy"}); }
- return pro::proxy_invoke<false, pro::details::format_dispatch,
- pro::details::format_overload_t<CharT>>(p, spec_, fc);
- }
- private:
- basic_string_view<CharT> spec_;
- };
- } // namespace std
- #endif // __STDC_HOSTED__
- #undef ___PRO_THROW
- #undef ___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE
- #endif // _MSFT_PROXY_
|