Skip to content
This repository was archived by the owner on Jan 29, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions docs/spec/ProAccessible.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Named requirements: *ProAccessible*

Given that `F` is a type meeting the [*ProBasicFacade* requirements](ProBasicFacade.md), a type `T` meets the *ProAccessible* requirements of type `F`, if the following expressions are well-formed and have the specified semantics.
A type `T` meets the *ProAccessible* requirements of types `Args...` if the following expressions are well-formed and have the specified semantics.

| Expressions | Semantics |
| ---------------------------------- | ------------------------------------------------------------ |
| `typename T::template accessor<F>` | A type that provides accessibility to `proxy`. It shall be a *nothrow-default-constructible*, *trivially-copyable* type, and shall not be [final](https://en.cppreference.com/w/cpp/language/final). |
| Expressions | Semantics |
| ---------------------------------------- | ------------------------------------------------------------ |
| `typename T::template accessor<Args...>` | A type that provides accessibility to `proxy`. It shall be a *nothrow-default-constructible*, *trivially-copyable* type, and shall not be [final](https://en.cppreference.com/w/cpp/language/final). |

## See Also

- [class template `proxy`](proxy/README.md)
- [class template `proxy_indirect_accessor`](proxy_indirect_accessor.md)
7 changes: 5 additions & 2 deletions docs/spec/proxy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ class proxy;

Class template `proxy` is a general-purpose polymorphic wrapper for C++ objects. Unlike other polymorphic wrappers in the C++ standard (e.g., [`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function), [`std::move_only_function`](https://en.cppreference.com/w/cpp/utility/functional/move_only_function), [`std::any`](https://en.cppreference.com/w/cpp/utility/any), etc.), `proxy` is based on pointer semantics. It supports flexible lifetime management without runtime [garbage collection (GC)](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)), and offers best-in-class code generation quality, extendibility and accessibility.

As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`. For each type `T` in `Cs` or `Rs`, if `T` meets the [*ProAccessible* requirements](../ProAccessible.md) of `F`, `typename T::template accessor<F>` is inherited by `proxy<F>` when `T::is_direct` is `true`. Otherwise, it is inherited by [`proxy_indirect_accessor`](../proxy_indirect_accessor.md), the return type of [`operator*`](indirection.md), when `T::is_direct` is `false`. It is recommended to use [`facade_builder`](../basic_facade_builder/README.md) to define a facade type.

Any instance of `proxy<F>` at any given point in time either *contains a value* or *does not contain a value*. If a `proxy<F>` *contains a value*, the type of the value shall be a pointer type `P` where [`proxiable<P, F>`](../proxiable.md) is `true`, and the value is guaranteed to be allocated as part of the `proxy` object footprint, i.e. no dynamic memory allocation occurs. However, `P` may allocate during its construction, depending on its implementation.

As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`.

- For each type `C` in `Cs`, if `C::is_direct` is `true` and `typename C::dispatch_type` meets the [*ProAccessible* requirements](../ProAccessible.md) of `proxy<F>, typename C::dispatch_type, substituted-overload-types...`, `typename C::dispatch_type::template accessor<proxy<F>, typename C::dispatch_type, substituted-overload-types...>` is inherited by `proxy<F>`. Let `Os...` be the element types of `typename C::overload_types`, `substituted-overload-types...` is [`substituted-overload<Os, F>...`](../ProOverload.md).
- For each type `R` in `Rs`, if `R::is_direct` is `true` and `typename R::reflector_type` meets the [*ProAccessible* requirements](../ProAccessible.md) of `proxy<F>, typename R::reflector_type`, `typename R::reflector_type::template accessor<proxy<F>, typename R::reflector_type` is inherited by `proxy<F>`.

## Member Types

| Name | Description |
Expand Down
5 changes: 4 additions & 1 deletion docs/spec/proxy_indirect_accessor.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ template <facade F>
class proxy_indirect_accessor;
```

Class template `proxy_indirect_accessor` provides indirection accessibility for `proxy`. As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`. For each type `T` in `Cs` or `Rs`, if `T` meets the [*ProAccessible* requirements](ProAccessible.md) of `F` and `T::is_direct` is `false`, `typename T::template accessor<F>` is inherited by `proxy_indirect_accessor<F>`.
Class template `proxy_indirect_accessor` provides indirection accessibility for `proxy`. As per `facade<F>`, `typename F::convention_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Cs`, and `typename F::reflection_types` shall be a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type containing any number of distinct types `Rs`.

- For each type `C` in `Cs`, if `C::is_direct` is `false` and `typename C::dispatch_type` meets the [*ProAccessible* requirements](ProAccessible.md) of `proxy_indirect_accessor<F>, typename C::dispatch_type, substituted-overload-types...`, `typename C::dispatch_type::template accessor<proxy<F>, typename C::dispatch_type, substituted-overload-types...>` is inherited by `proxy_indirect_accessor<F>`. Let `Os...` be the element types of `typename C::overload_types`, `substituted-overload-types...` is [`substituted-overload<Os, F>...`](ProOverload.md).
- For each type `R` in `Rs`, if `R::is_direct` is `false` and `typename R::reflector_type` meets the [*ProAccessible* requirements](ProAccessible.md) of `proxy_indirect_accessor<F>, typename R::reflector_type`, `typename R::reflector_type::template accessor<proxy_indirect_accessor<F>, typename R::reflector_type` is inherited by `proxy_indirect_accessor<F>`.

## Member Functions

Expand Down
183 changes: 89 additions & 94 deletions include/proxy/v4/proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ struct reduction_traits {
using type = typename R<Args..., O, I>::type;
};

template <class O, class I>
struct composition_reduction : std::type_identity<O> {};
template <template <class...> class T, class... Os, class I>
requires(!std::is_void_v<I>)
struct composition_reduction<T<Os...>, I> : std::type_identity<T<Os..., I>> {};
template <template <class...> class T, class... Os, class... Is>
struct composition_reduction<T<Os...>, T<Is...>>
: std::type_identity<T<Os..., Is...>> {};
template <class T, class... Us>
using composite_t = recursive_reduction_t<
reduction_traits<composition_reduction>::template type, T, Us...>;

template <class Expr>
consteval bool is_consteval(Expr) {
return requires { typename std::bool_constant<(Expr{}(), false)>; };
Expand Down Expand Up @@ -391,25 +403,12 @@ struct invocation_meta {
};

template <class... Ms>
struct composite_meta_impl : Ms... {
constexpr composite_meta_impl() noexcept = default;
struct composite_meta : Ms... {
constexpr composite_meta() noexcept = default;
template <class P>
constexpr explicit composite_meta_impl(std::in_place_type_t<P>) noexcept
constexpr explicit composite_meta(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... Ms>
using composite_meta =
recursive_reduction_t<reduction_traits<meta_reduction>::template type,
composite_meta_impl<>, Ms...>;

template <class T>
consteval bool is_is_direct_well_formed() {
Expand Down Expand Up @@ -439,14 +438,33 @@ template <class C>
struct basic_conv_traits<C>
: instantiated_t<basic_conv_traits_impl, typename C::overload_types, C> {};

template <class T>
struct a11y_traits_impl
: std::conditional<std::is_nothrow_default_constructible_v<T> &&
std::is_trivially_copyable_v<T> &&
!std::is_final_v<T>,
T, void> {};
template <class SFINAE, class T, class... Args>
struct a11y_traits : std::type_identity<void> {};
template <class T, class... Args>
struct a11y_traits<std::void_t<typename T::template accessor<Args...>>, T,
Args...>
: a11y_traits_impl<typename T::template accessor<Args...>> {};
template <class T, class... Args>
using accessor_t = typename a11y_traits<void, T, Args...>::type;

template <class C, class F, class... Os>
struct conv_traits_impl : inapplicable_traits {};
template <class C, class F, class... Os>
requires(overload_traits<substituted_overload_t<Os, F>>::applicable && ...)
struct conv_traits_impl<C, F, Os...> : applicable_traits {
using meta = composite_meta_impl<
invocation_meta<F, C::is_direct, typename C::dispatch_type,
substituted_overload_t<Os, F>>...>;
using meta =
composite_meta<invocation_meta<F, C::is_direct, typename C::dispatch_type,
substituted_overload_t<Os, F>>...>;
template <class T>
using accessor =
accessor_t<typename C::dispatch_type, T, typename C::dispatch_type,
substituted_overload_t<Os, F>...>;

template <class P>
static consteval bool diagnose_proxiable() {
Expand Down Expand Up @@ -570,58 +588,44 @@ template <class F, class D, class ONE, class OE, constraint_level C>
using lifetime_meta_t = typename lifetime_meta_traits<F, D, ONE, OE, C>::type;

template <class... As>
struct PRO4D_ENFORCE_EBO composite_accessor_impl : As... {};
struct PRO4D_ENFORCE_EBO composite_accessor : As... {};

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 <class IsDirect, class F, class O, class I>
struct composite_accessor_reduction : std::type_identity<O> {};
template <class IsDirect, class F, class... As, class I>
requires(IsDirect::value == 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, class... Ts>
using composite_accessor = recursive_reduction_t<
reduction_traits<composite_accessor_reduction, std::bool_constant<IsDirect>,
F>::template type,
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 C, class F, bool IsDirect>
struct conv_accessor_traits : std::type_identity<void> {};
template <class C, class F>
requires(!C::is_direct)
struct conv_accessor_traits<C, F, false>
: std::type_identity<typename conv_traits<C, F>::template accessor<
proxy_indirect_accessor<F>>> {};
template <class C, class F>
requires(C::is_direct)
struct conv_accessor_traits<C, F, true>
: std::type_identity<
typename conv_traits<C, F>::template accessor<proxy<F>>> {};
template <class C, class F, bool IsDirect>
using conv_accessor_t = typename conv_accessor_traits<C, F, IsDirect>::type;

template <class R, class F, bool IsDirect>
struct refl_accessor_traits : std::type_identity<void> {};
template <class R, class F>
requires(!R::is_direct)
struct refl_accessor_traits<R, F, false>
: std::type_identity<
accessor_t<typename R::reflector_type, proxy_indirect_accessor<F>,
typename R::reflector_type>> {};
template <class R, class F>
requires(R::is_direct)
struct refl_accessor_traits<R, F, true>
: std::type_identity<accessor_t<typename R::reflector_type, proxy<F>,
typename R::reflector_type>> {};
template <class R, class F, bool IsDirect>
using refl_accessor_t = typename refl_accessor_traits<R, F, IsDirect>::type;

struct tr_blocker {
tr_blocker() = default;
tr_blocker(const tr_blocker&) noexcept {}
tr_blocker& operator=(const tr_blocker&) noexcept { return *this; }
};
template <class A, bool TR>
struct conditional_tr_accessor_traits : std::type_identity<A> {};
template <class... As>
struct conditional_tr_accessor_traits<composite_accessor_impl<As...>, false>
: std::type_identity<composite_accessor_impl<tr_blocker, As...>> {};
template <class A, bool TR>
using conditional_tr_accessor_t =
typename conditional_tr_accessor_traits<A, TR>::type;

template <class P>
struct ptr_traits : inapplicable_traits {};
Expand Down Expand Up @@ -716,9 +720,12 @@ struct facade_conv_traits_impl : inapplicable_traits {};
template <class F, class... Cs>
requires(conv_traits<Cs, F>::applicable && ...)
struct facade_conv_traits_impl<F, Cs...> : applicable_traits {
using conv_meta = composite_meta<typename conv_traits<Cs, F>::meta...>;
using conv_indirect_accessor = composite_accessor<false, F, Cs...>;
using conv_direct_accessor = composite_accessor<true, F, Cs...>;
using conv_meta =
composite_t<composite_meta<>, typename conv_traits<Cs, F>::meta...>;
using conv_indirect_accessor =
composite_t<composite_accessor<>, conv_accessor_t<Cs, F, false>...>;
using conv_direct_accessor =
composite_t<composite_accessor<>, conv_accessor_t<Cs, F, true>...>;

template <class P>
static consteval bool diagnose_proxiable_conv() {
Expand All @@ -737,8 +744,10 @@ struct facade_conv_traits_impl<F, Cs...> : applicable_traits {
template <class F, class... Rs>
struct facade_refl_traits_impl {
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...>;
using refl_indirect_accessor =
composite_t<composite_accessor<>, refl_accessor_t<Rs, F, false>...>;
using refl_direct_accessor =
composite_t<composite_accessor<>, refl_accessor_t<Rs, F, true>...>;

template <class P>
static consteval bool diagnose_proxiable_refl() {
Expand All @@ -759,7 +768,8 @@ template <class F>
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 meta = composite_meta<
using meta = composite_t<
composite_meta<>,
lifetime_meta_t<F, copy_dispatch, void(proxy<F>&) const noexcept,
void(proxy<F>&) const, F::copyability>,
lifetime_meta_t<F, relocate_dispatch, void(proxy<F>&) && noexcept,
Expand All @@ -768,12 +778,13 @@ struct facade_traits<F>
F::destructibility>,
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 = conditional_tr_accessor_t<
merged_composite_accessor<typename facade_traits::conv_direct_accessor,
typename facade_traits::refl_direct_accessor>,
F::relocatability == constraint_level::trivial>;
composite_t<typename facade_traits::conv_indirect_accessor,
typename facade_traits::refl_indirect_accessor>;
using direct_accessor = composite_t<
typename facade_traits::conv_direct_accessor,
typename facade_traits::refl_direct_accessor,
std::conditional_t<F::relocatability == constraint_level::trivial, void,
tr_blocker>>;

template <class P>
static consteval void diagnose_proxiable() {
Expand Down Expand Up @@ -835,9 +846,9 @@ template <class M>
struct meta_ptr_traits_impl : std::type_identity<meta_ptr_indirect_impl<M>> {};
template <class F, bool IsDirect, class D, class O, class... Ms>
struct meta_ptr_traits_impl<
composite_meta_impl<invocation_meta<F, IsDirect, D, O>, Ms...>>
composite_meta<invocation_meta<F, IsDirect, D, O>, Ms...>>
: std::type_identity<meta_ptr_direct_impl<
composite_meta_impl<invocation_meta<F, IsDirect, D, O>, Ms...>,
composite_meta<invocation_meta<F, IsDirect, D, O>, Ms...>,
invocation_meta<F, IsDirect, D, O>>> {};
template <class M>
struct meta_ptr_traits : std::type_identity<meta_ptr_indirect_impl<M>> {};
Expand Down Expand Up @@ -1799,32 +1810,16 @@ consteval std::size_t max_align_of(std::size_t value) {
return value < alignof(std::max_align_t) ? value : alignof(std::max_align_t);
}

template <class SFINAE, class T, class... Args>
struct accessor_instantiation_traits : std::type_identity<void> {};
template <class T, class... Args>
struct accessor_instantiation_traits<
std::void_t<typename T::template accessor<Args...>>, T, Args...>
: std::type_identity<typename T::template accessor<Args...>> {};
template <class T, class F, bool IsDirect, class... Args>
using instantiated_accessor_t = typename accessor_instantiation_traits<
void, T, std::conditional_t<IsDirect, proxy<F>, proxy_indirect_accessor<F>>,
T, 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, substituted_overload_t<Os, F>...>;
};
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, std::size_t MaxSize, std::size_t MaxAlign,
constraint_level Copyability, constraint_level Relocatability,
Expand Down
Loading