diff --git a/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md b/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md index 55f41eb..1082c8f 100644 --- a/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md +++ b/docs/PRO_DEF_FREE_AS_MEM_DISPATCH.md @@ -16,7 +16,7 @@ PRO_DEF_FREE_AS_MEM_DISPATCH(dispatch_name, func_name, accessibility_func_name); `(1)` Equivalent to `PRO_DEF_FREE_AS_MEM_DISPATCH(dispatch_name, func_name, func_name);` -`(2)` Defines a class named `dispatch_name` of free function call expressions of `func_name` with accessibility via a member function. `dispatch_name` meets the [*ProAccessible*](ProAccessible.md) requirements of types `F`, `C`, and `Os...`, where `F` models concept [`facade`](facade.md), `C` is a tuple element type defined in `typename F::convention_types`, and each type `O` (possibly qualified with *cv ref noex*) in `Os...` is a tuple element type defined in `typename C::overload_types`. The member functions provided by `typename dispatch_name::template accessor` are named `accessibility_func_name`. Effectively equivalent to: +`(2)` Defines a class named `dispatch_name` of free function call expressions of `func_name` with accessibility via member function overloads named `accessibility_func_name`. Effectively equivalent to: ```cpp struct dispatch_name { diff --git a/docs/PRO_DEF_FREE_DISPATCH.md b/docs/PRO_DEF_FREE_DISPATCH.md index 67e5e71..e873d77 100644 --- a/docs/PRO_DEF_FREE_DISPATCH.md +++ b/docs/PRO_DEF_FREE_DISPATCH.md @@ -16,7 +16,7 @@ PRO_DEF_FREE_DISPATCH(dispatch_name, func_name, accessibility_func_name); `(1)` Equivalent to `PRO_DEF_FREE_DISPATCH(dispatch_name, func_name, func_name);` -`(2)` Defines a class named `dispatch_name` of free function call expressions of `func_name` with accessibility. `dispatch_name` meets the [*ProAccessible*](ProAccessible.md) requirements of types `F`, `C`, and `Os...`, where `F` models concept [`facade`](facade.md), `C` is a tuple element type defined in `typename F::convention_types`, and each type `O` (possibly qualified with *cv ref noex*) in `Os...` is a tuple element type defined in `typename C::overload_types`. Let `accessor_arg` be `std::conditional_t, proxy_indirect_accessor>`. The functions provided by `typename dispatch_name::template accessor` are named `accessibility_func_name` and can be found by [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl) when `accessor_arg` is an associated class of the arguments. Effectively equivalent to: +`(2)` Defines a class named `dispatch_name` of free function call expressions of `func_name` with accessibility via free function overloads named `accessibility_func_name`. Effectively equivalent to: ```cpp struct dispatch_name { @@ -27,16 +27,17 @@ struct dispatch_name { return func_name(std::forward(self), std::forward(args)...); } - template struct accessor { + template + struct accessor { accessor() = delete; }; - template - requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) - struct accessor : accessor... {}; - template - struct accessor { + template + requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) + struct accessor : accessor... {}; + template + struct accessor { friend R accessibility_func_name(accessor_arg cv ref self, Args... args) noex { - return pro::proxy_invoke(pro::access_proxy(std::forward(self)), std::forward(args)...); + return pro::proxy_invoke(pro::access_proxy(std::forward(self)), std::forward(args)...); } }; } diff --git a/docs/PRO_DEF_MEM_DISPATCH.md b/docs/PRO_DEF_MEM_DISPATCH.md index f012aa5..2da23c4 100644 --- a/docs/PRO_DEF_MEM_DISPATCH.md +++ b/docs/PRO_DEF_MEM_DISPATCH.md @@ -16,7 +16,7 @@ PRO_DEF_MEM_DISPATCH(dispatch_name, func_name, accessibility_func_name); `(1)` Equivalent to `PRO_DEF_MEM_DISPATCH(dispatch_name, func_name, func_name);` -`(2)` Defines a class named `dispatch_name` of member function call expressions of `func_name` with accessibility. `dispatch_name` meets the [*ProAccessible*](ProAccessible.md) requirements of types `F`, `C`, and `Os...`, where `F` models concept [`facade`](facade.md), `C` is a tuple element type defined in `typename F::convention_types`, and each type `O` (possibly qualified with *cv, ref, noex*) in `Os...` is a tuple element type defined in `typename C::overload_types`. The member functions provided by `typename dispatch_name::template accessor` are named `accessibility_func_name`. Effectively equivalent to: +`(2)` Defines a class named `dispatch_name` of member function call expressions of `func_name` with accessibility via member function overloads named `accessibility_func_name`. Effectively equivalent to: ```cpp struct dispatch_name { @@ -27,19 +27,19 @@ struct dispatch_name { return std::forward(self).func_name(std::forward(args)...); } - template + template struct accessor { accessor() = delete; }; - template - requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) - struct accessor : accessor... { - using accessor::accessibility_func_name ...; + template + requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) + struct accessor : accessor... { + using accessor::accessibility_func_name ...; }; - template - struct accessor { + template + struct accessor { R accessibility_func_name(Args... args) cv ref noex { - return pro::proxy_invoke(pro::access_proxy(std::forward(*this)), std::forward(args)...); + return pro::proxy_invoke(pro::access_proxy(std::forward(*this)), std::forward(args)...); } }; } diff --git a/docs/ProAccessible.md b/docs/ProAccessible.md index fde8a85..a568256 100644 --- a/docs/ProAccessible.md +++ b/docs/ProAccessible.md @@ -1,10 +1,10 @@ # Named requirements: *ProAccessible* -Given that `F` is a type meeting the [*ProBasicFacade* requirements](ProBasicFacade.md), a type `T` meets the *ProAccessible* requirements of types `F, Args...`, if the following expressions are well-formed and have the specified semantics. +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. -| Expressions | Semantics | -| ------------------------------------------- | ------------------------------------------------------------ | -| `typename T::template accessor` | 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` | 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 diff --git a/docs/access_proxy.md b/docs/access_proxy.md index d9f2ded..c36ff8d 100644 --- a/docs/access_proxy.md +++ b/docs/access_proxy.md @@ -48,14 +48,13 @@ int main() { std::cout << ToString(*p) << "\n"; // Prints: "123" // How it works behind the scenes - using Convention = std::tuple_element_t<0u, Stringable::convention_types>; - using Accessor = Convention::accessor; + using Accessor = FreeToString::accessor; static_assert(std::is_base_of_v>); Accessor& a = static_cast(*p); pro::proxy& p2 = pro::access_proxy(a); std::cout << std::boolalpha << (&p == &p2) << "\n"; // Prints: "true" because access_proxy converts // an accessor back to the original proxy - auto result = pro::proxy_invoke(p2); + auto result = pro::proxy_invoke(p2); std::cout << result << "\n"; // Prints: "123" } ``` diff --git a/docs/basic_facade_builder/add_convention.md b/docs/basic_facade_builder/add_convention.md index bde23a0..4c64e4a 100644 --- a/docs/basic_facade_builder/add_convention.md +++ b/docs/basic_facade_builder/add_convention.md @@ -18,12 +18,12 @@ The alias templates `add_convention`, `add_indirect_convention`, and `add_direct - `IC::is_direct` is `false`. - `typename IC::dispatch_type` is `D`. - `typename IC::overload_types` is a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type of distinct types in `Os`. - - `typename IC::template accessor` is `typename D::template accessor` if applicable. + - `typename IC::template accessor` is `typename D::template accessor` if applicable. - `add_direct_convention` merges an implementation-defined convention type `IC` into `Cs`, where: - `IC::is_direct` is `true`. - `typename IC::dispatch_type` is `D`. - `typename IC::overload_types` is a [tuple-like](https://en.cppreference.com/w/cpp/utility/tuple/tuple-like) type of distinct types in `Os`. - - `typename IC::template accessor` is `typename D::template accessor` if applicable. + - `typename IC::template accessor` is `typename D::template accessor` if applicable. When `Cs` already contains a convention type `IC2` where `IC2::is_direct == IC::is_direct && std::is_same_v` is `true`, `Os` merges with `typename IC2::overload_types` and removes duplicates, and `std::tuple_size_v` shall not change. diff --git a/docs/basic_facade_builder/add_reflection.md b/docs/basic_facade_builder/add_reflection.md index df2ae0e..51f30c9 100644 --- a/docs/basic_facade_builder/add_reflection.md +++ b/docs/basic_facade_builder/add_reflection.md @@ -14,16 +14,16 @@ using add_direct_reflection = basic_facade_builder; The alias templates `add_reflection`, `add_indirect_reflection` and `add_direct_reflection` of `basic_facade_builder` add reflection types to the template parameters. Specifically, - `add_reflection` is equivalent to `add_indirect_reflection`. -- `add_indirect_reflection` merges an implementation-defined reflection type `R2` into `Rs`, where: - - `R2::is_direct` is `false`. - - `typename R2::reflector_type` is `R`. - - `typename R2::template accessor` is `typename R2::template accessor` if applicable. -- `add_direct_reflection` merges an implementation-defined reflection type `R2` into `Rs`, where: - - `R2::is_direct` is `true`. - - `typename R2::reflector_type` is `R`. - - `typename R2::template accessor` is `typename R2::template accessor` if applicable. +- `add_indirect_reflection` merges an implementation-defined reflection type `Refl` into `Rs`, where: + - `Refl::is_direct` is `false`. + - `typename Refl::reflector_type` is `R`. + - `typename Refl::template accessor` is `typename R::template accessor` if applicable. +- `add_direct_reflection` merges an implementation-defined reflection type `Refl` into `Rs`, where: + - `Refl::is_direct` is `true`. + - `typename Refl::reflector_type` is `R`. + - `typename Refl::template accessor` is `typename R::template accessor` if applicable. -When `Rs` already contains `R2`, the template parameters shall not change. +When `Rs` already contains `Refl`, the template parameters shall not change. ## Notes @@ -42,10 +42,10 @@ class RttiReflector { template constexpr explicit RttiReflector(std::in_place_type_t) : type_(typeid(T)) {} - template + template struct accessor { const char* GetTypeName() const noexcept { - const RttiReflector& self = pro::proxy_reflect(pro::access_proxy(*this)); + const RttiReflector& self = pro::proxy_reflect(pro::access_proxy(*this)); return self.type_.name(); } }; diff --git a/docs/explicit_conversion_dispatch/accessor.md b/docs/explicit_conversion_dispatch/accessor.md index 8d6716c..9bb9614 100644 --- a/docs/explicit_conversion_dispatch/accessor.md +++ b/docs/explicit_conversion_dispatch/accessor.md @@ -2,27 +2,27 @@ ```cpp // (1) -template +template struct accessor { accessor() = delete; }; // (2) -template - requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) -struct accessor : accessor... { - using accessor::operator return-type-of...; +template + requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) +struct accessor : accessor... { + using accessor::operator return-type-of...; }; // (3) -template -struct accessor { +template +struct accessor { explicit operator T() cv ref noex; }; ``` `(1)` The default implementation of `accessor` is not constructible. -`(2)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are default-constructible, inherits all `accessor...` types and `using` their `operator return-type-of`. `return-type-of` denotes the *return type* of the overload type `O`. +`(2)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are default-constructible, inherits all `accessor...` types and `using` their `operator return-type-of`. `return-type-of` denotes the *return type* of the overload type `O`. -`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an explicit `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return proxy_invoke(access_proxy(std::forward(*this)))`. +`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an explicit `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return proxy_invoke(access_proxy(std::forward(*this)))`. diff --git a/docs/implicit_conversion_dispatch/accessor.md b/docs/implicit_conversion_dispatch/accessor.md index 0b78300..95f9abb 100644 --- a/docs/implicit_conversion_dispatch/accessor.md +++ b/docs/implicit_conversion_dispatch/accessor.md @@ -2,27 +2,27 @@ ```cpp // (1) -template +template struct accessor { accessor() = delete; }; // (2) -template - requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) -struct accessor : accessor... { - using accessor::operator return-type-of...; +template + requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) +struct accessor : accessor... { + using accessor::operator return-type-of...; }; // (3) -template -struct accessor { +template +struct accessor { operator T() cv ref noex; }; ``` `(1)` The default implementation of `accessor` is not constructible. -`(2)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are default-constructible, inherits all `accessor...` types and `using` their `operator return-type-of`. `return-type-of` denotes the *return type* of the overload type `O`. +`(2)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are default-constructible, inherits all `accessor...` types and `using` their `operator return-type-of`. `return-type-of` denotes the *return type* of the overload type `O`. -`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an implicit `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return proxy_invoke(access_proxy(std::forward(*this)))`. +`(3)` When `sizeof...(Os)` is `1` and the only type `O` in `Os` is `T() cv ref noex`, provides an implicit `operator T()` with the same *cv ref noex* specifiers. `accessor::operator T()` is equivalent to `return proxy_invoke(access_proxy(std::forward(*this)))`. diff --git a/docs/operator_dispatch/accessor.md b/docs/operator_dispatch/accessor.md index 69f1e54..8b458ae 100644 --- a/docs/operator_dispatch/accessor.md +++ b/docs/operator_dispatch/accessor.md @@ -2,7 +2,7 @@ ```cpp // (1) -template +template struct accessor { accessor() = delete; }; @@ -16,14 +16,14 @@ For different `Sign` and `Rhs`, `operator_dispatch::accessor` has dif ```cpp // (2) -template - requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) -struct accessor : accessor... { - using accessor::operator sop...; +template + requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) +struct accessor : accessor... { + using accessor::operator sop...; }; ``` -`(2)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are default-constructible types, inherits all `accessor...` types and `using` their `operator sop`. +`(2)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are default-constructible types, inherits all `accessor...` types and `using` their `operator sop`. When `Rhs` is `false`, the other specializations are defined as follows, where `sizeof...(Os)` is `1` and the only type `O` qualified with `cv ref noex` (let `ACCESS_PROXY_EXPR` be `access_proxy(std::forward(*this))`): @@ -33,13 +33,13 @@ When `Sign` is one of `"+"`, `"-"`, `"*"`, `"/"`, `"%"`, `"++"`, `"--"`, `"=="`, ```cpp // (3) -template -struct accessor { +template +struct accessor { R operator sop (Args... args) cv ref noex; } ``` -`(3)` Provides an `operator sop(Args...)` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop(Args...)` is equivalent to `return proxy_invoke(ACCESS_PROXY_EXPR, std::forward(args)...)`. +`(3)` Provides an `operator sop(Args...)` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop(Args...)` is equivalent to `return proxy_invoke(ACCESS_PROXY_EXPR, std::forward(args)...)`. ### `!` and `~` @@ -47,13 +47,13 @@ When `Sign` is either `!` and `~`, ```cpp // (4) -template -struct accessor { +template +struct accessor { R operator sop () cv ref noex; } ``` -`(4)` Provides an `operator sop()` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop()` is equivalent to `return proxy_invoke(ACCESS_PROXY_EXPR)`. +`(4)` Provides an `operator sop()` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop()` is equivalent to `return proxy_invoke(ACCESS_PROXY_EXPR)`. ### Assignment SOPs @@ -61,26 +61,26 @@ When `Sign` is one of `"+="`, `"-="`, `"*="`, `"/="`, `"&="`, `"|="`, `"^="`, `" ```cpp // (5) -template -struct accessor { +template +struct accessor { /* see below */ operator sop (Arg arg) cv ref noex; } ``` -`(4)` Provides an `operator sop(Arg)` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop(Arg)` calls `proxy_invoke(ACCESS_PROXY_EXPR, std::forward(arg))` and returns `ACCESS_PROXY_EXPR` when `C::is_direct` is `true`, or otherwise, returns `*ACCESS_PROXY_EXPR` when `C::is_direct` is `false`. +`(4)` Provides an `operator sop(Arg)` with the same *cv ref noex* specifiers as of the overload type. `accessor::operator sop(Arg)` calls `proxy_invoke(ACCESS_PROXY_EXPR, std::forward(arg))` and returns `ACCESS_PROXY_EXPR` when `IsDirect` is `true`, or otherwise, returns `*ACCESS_PROXY_EXPR` when `IsDirect` is `false`. ## Right-Hand-Side Operand Specializations ```cpp // (6) -template - requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) -struct accessor : accessor... {}; +template + requires(sizeof...(Os) > 1u && (std::is_constructible_v> && ...)) +struct accessor : accessor... {}; ``` -`(6)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are default-constructible types, inherits all `accessor...` types. +`(6)` When `sizeof...(Os)` is greater than `1`, and `accessor...` are default-constructible types, inherits all `accessor...` types. -When `Rhs` is `true`, the other specializations are defined as follows, where `sizeof...(Os)` is `1` and the only type `O` qualified with `cv ref noex` (let `accessor_arg` be `std::conditional_t, proxy_indirect_accessor>`, `ACCESS_PROXY_EXPR` be `access_proxy(std::forward(self))`): +When `Rhs` is `true`, the other specializations are defined as follows, where `sizeof...(Os)` is `1` and the only type `O` qualified with `cv ref noex` (let `accessor_arg` be `std::conditional_t, proxy_indirect_accessor>`, `ACCESS_PROXY_EXPR` be `access_proxy(std::forward(self))`): ### Regular SOPs @@ -88,13 +88,13 @@ When `Sign` is one of `"+"`, `"-"`, `"*"`, `"/"`, `"%"`, `"=="`, `"!="`, `">"`, ```cpp // (7) -template -struct accessor { +template +struct accessor { friend R operator sop (Arg arg, accessor_arg cv ref self) noex; } ``` -`(7)` Provides a `friend operator sop(Arg arg, accessor_arg cv ref self)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, accessor_arg cv ref self)` is equivalent to `return proxy_invoke(ACCESS_PROXY_EXPR, std::forward(arg))`. +`(7)` Provides a `friend operator sop(Arg arg, accessor_arg cv ref self)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, accessor_arg cv ref self)` is equivalent to `return proxy_invoke(ACCESS_PROXY_EXPR, std::forward(arg))`. ### Assignment SOPs @@ -102,10 +102,10 @@ When `Sign` is one of `"+="`, `"-="`, `"*="`, `"/="`, `"&="`, `"|="`, `"^="`, `" ```cpp // (8) -template -struct accessor { +template +struct accessor { friend /* see below */ operator sop (Arg arg, accessor_arg cv ref self) noex; } ``` -`(8)` Provides a `friend operator sop(Arg arg, accessor_arg cv ref self)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, accessor_arg cv ref self)` calls `proxy_invoke(ACCESS_PROXY_EXPR, std::forward(arg))` and returns `ACCESS_PROXY_EXPR` when `C::is_direct` is `true`, or otherwise, returns `*ACCESS_PROXY_EXPR` when `C::is_direct` is `false`. +`(8)` Provides a `friend operator sop(Arg arg, accessor_arg cv ref self)` with the same *noex* specifiers as of the overload type. `accessor::operator sop(Arg arg, accessor_arg cv ref self)` calls `proxy_invoke(ACCESS_PROXY_EXPR, std::forward(arg))` and returns `ACCESS_PROXY_EXPR` when `IsDirect` is `true`, or otherwise, returns `*ACCESS_PROXY_EXPR` when `IsDirect` is `false`. diff --git a/docs/proxy_invoke.md b/docs/proxy_invoke.md index 3495a92..88c027d 100644 --- a/docs/proxy_invoke.md +++ b/docs/proxy_invoke.md @@ -1,30 +1,30 @@ # Function template `proxy_invoke` ```cpp -template +template /* see below */ proxy_invoke(proxy& p, Args&&... args); -template +template /* see below */ proxy_invoke(const proxy& p, Args&&... args); -template +template /* see below */ proxy_invoke(proxy&& p, Args&&... args); -template +template /* see below */ proxy_invoke(const proxy&& p, Args&&... args); ``` -Invokes a `proxy` with a specified convention type, an overload type, and arguments. `C` is required to be defined in `typename F::convention_types`. `O` is required to be defined in `typename C::overload_types`. +Invokes a `proxy` with a specified dispatch type, an overload type, and arguments. There shall be a convention type `Conv` defined in `typename F::convention_types` where `Conv::is_direct == IsDirect && std::is_same_v` is `true`. `O` is required to be defined in `typename Conv::overload_types`. Let `ptr` be the contained value of `p` with the same cv ref-qualifiers, `Args2...` be the argument types of `O`, `R` be the return type of `O`, -- if `C::is_direct` is `true`, let `v` be `std::forward(ptr)`, or otherwise, -- if `C::is_direct` is `false`, let `v` be `*std::forward(ptr)`, +- if `IsDirect` is `true`, let `v` be `std::forward(ptr)`, or otherwise, +- if `IsDirect` is `false`, let `v` be `*std::forward(ptr)`, equivalent to: -- [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(typename C::dispatch_type{}, std::forward(v), static_cast(args)...)` if the expression is well-formed, or otherwise, -- [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(typename C::dispatch_type{}, nullptr, static_cast(args)...)`. +- [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, std::forward(v), static_cast(args)...)` if the expression is well-formed, or otherwise, +- [`INVOKE`](https://en.cppreference.com/w/cpp/utility/functional)`(D{}, nullptr, static_cast(args)...)`. The behavior is undefined if `p` does not contain a value. @@ -32,8 +32,8 @@ The behavior is undefined if `p` does not contain a value. It is generally not recommended to call `proxy_invoke` directly. Using an [`accessor`](ProAccessible.md) is usually a better option with easier and more descriptive syntax. If the facade type `F` is defined with the recommended facilities, it has full accessibility support. Specifically, when -- the underlying dispatch type `typename C::dispatch_type` is defined via [macro `PRO_DEF_MEM_DISPATCH`](PRO_DEF_MEM_DISPATCH.md), [macro `PRO_DEF_FREE_DISPATCH`](PRO_DEF_FREE_DISPATCH.md), or is a specialization of either [`operator_dispatch`](operator_dispatch.md) or [`conversion_dispatch`](conversion_dispatch.md), and -- the convention is defined via [`facade_builder`](basic_facade_builder.md). +- `D` is defined via [macro `PRO_DEF_MEM_DISPATCH`](PRO_DEF_MEM_DISPATCH.md), [macro `PRO_DEF_FREE_DISPATCH`](PRO_DEF_FREE_DISPATCH.md), or is a specialization of either [`operator_dispatch`](operator_dispatch.md) or [`conversion_dispatch`](conversion_dispatch.md), and +- the convention type `Conv` is defined via [`facade_builder`](basic_facade_builder.md). ## Example @@ -53,9 +53,7 @@ int main() { int a = 123; pro::proxy p = &a; std::cout << ToString(*p) << "\n"; // Invokes with accessor, prints: "123" - - using C = std::tuple_element_t<0u, Stringable::convention_types>; - std::cout << pro::proxy_invoke(p) << "\n"; // Invokes with proxy_invoke, also prints: "123" + std::cout << pro::proxy_invoke(p) << "\n"; // Invokes with proxy_invoke, also prints: "123" } ``` diff --git a/docs/proxy_reflect.md b/docs/proxy_reflect.md index 5e84808..9788863 100644 --- a/docs/proxy_reflect.md +++ b/docs/proxy_reflect.md @@ -1,11 +1,11 @@ # Function template `proxy_reflect` ```cpp -template -/* see below */ proxy_reflect(const proxy& p) noexcept; +template +const R& proxy_reflect(const proxy& p) noexcept; ``` -Let `P` be the type of the contained value of `p`. Retrieves a value of type `const typename R::reflector_type&` constructed from [`std::in_place_type`](https://en.cppreference.com/w/cpp/utility/in_place), where `T` is `P` when `R::is_direct` is `true`, or otherwise `T` is `typename std::pointer_traits

::element_type` when `R::is_direct` is `false`. `R` is required to be defined in `typename F::reflection_types`. The behavior is undefined if `p` does not contain a value. +Let `P` be the type of the contained value of `p`. Retrieves a value of type `const R&` constructed from [`std::in_place_type`](https://en.cppreference.com/w/cpp/utility/in_place), where `T` is `P` when `IsDirect` is `true`, or otherwise `T` is `typename std::pointer_traits

::element_type` when `IsDirect` is `false`. There shall be a reflection type `Refl` defined in `typename F::reflection_types` where `Refl::is_direct == IsDirect && std::is_same_v` is `true`. The behavior is undefined if `p` does not contain a value. The reference obtained from `proxy_reflect()` may be invalidated if `p` is subsequently modified. @@ -28,10 +28,10 @@ class CopyabilityReflector { constexpr explicit CopyabilityReflector(std::in_place_type_t) : copyable_(std::is_copy_constructible_v) {} - template + template struct accessor { bool IsCopyable() const noexcept { - const CopyabilityReflector& self = pro::proxy_reflect(pro::access_proxy(*this)); + const CopyabilityReflector& self = pro::proxy_reflect(pro::access_proxy(*this)); return self.copyable_; } }; diff --git a/proxy.h b/proxy.h index 1bb6ba9..31692a6 100644 --- a/proxy.h +++ b/proxy.h @@ -261,15 +261,15 @@ inline void destruction_default_dispatcher(std::byte&) noexcept {} template struct overload_traits : inapplicable_traits {}; template struct overload_traits_impl : applicable_traits { - template + template struct meta_provider { template static constexpr auto get() -> func_ptr_t, Args...> { - if constexpr (!IS_DIRECT && + if constexpr (!IsDirect && invocable_dispatch_ptr_indirect) { return &indirect_conv_dispatcher; - } else if constexpr (IS_DIRECT && + } else if constexpr (IsDirect && invocable_dispatch_ptr_direct) { return &direct_conv_dispatcher; } else if constexpr (invocable_dispatch< @@ -283,9 +283,9 @@ struct overload_traits_impl : applicable_traits { using return_type = R; using view_type = R(Args...) const noexcept(NE); - template + template static constexpr bool applicable_ptr = - meta_provider::template get

() != nullptr; + meta_provider::template get

() != nullptr; static constexpr qualifier_type qualifier = Q; }; template @@ -393,21 +393,21 @@ struct conv_traits template using ptr_element_t = typename std::pointer_traits

::element_type; -template +template struct refl_meta { - template requires(R::is_direct) + template requires(IsDirect) constexpr explicit refl_meta(std::in_place_type_t

) : reflector(std::in_place_type

) {} - template requires(!R::is_direct) + template requires(!IsDirect) constexpr explicit refl_meta(std::in_place_type_t

) : reflector(std::in_place_type>) {} - typename R::reflector_type reflector; + R reflector; }; -template +template consteval bool is_reflector_well_formed() { - if constexpr (IS_DIRECT) { + if constexpr (IsDirect) { if constexpr (std::is_constructible_v>) { if constexpr (is_consteval([] { return R{std::in_place_type}; })) { return true; @@ -423,6 +423,8 @@ template requires(requires { typename R::reflector_type; } && is_is_direct_well_formed()) struct refl_traits : applicable_traits { + using meta = refl_meta; + template static constexpr bool applicable_ptr = is_reflector_well_formed(); @@ -489,31 +491,30 @@ template requires(std::is_nothrow_default_constructible_v && std::is_trivially_copyable_v && !std::is_final_v) struct accessor_traits_impl : std::type_identity {}; -template -struct sfinae_accessor_traits : std::type_identity {}; -template -struct sfinae_accessor_traits< - std::void_t>, T, Args...> - : accessor_traits_impl> {}; -template -using accessor_t = typename sfinae_accessor_traits::type; - -template +template +struct accessor_traits : std::type_identity {}; +template +struct accessor_traits>, T, F> + : accessor_traits_impl> {}; +template +using accessor_t = typename accessor_traits::type; + +template struct composite_accessor_reduction : std::type_identity {}; -template - requires(IS_DIRECT == I::is_direct && !std::is_void_v>) +template + requires(IsDirect == I::is_direct && !std::is_void_v>) struct composite_accessor_reduction< - IS_DIRECT, F, composite_accessor_impl, I> + IsDirect, F, composite_accessor_impl, I> : std::type_identity>> {}; -template +template struct composite_accessor_helper { template using reduction_t = - typename composite_accessor_reduction::type; + typename composite_accessor_reduction::type; }; -template +template using composite_accessor = recursive_reduction_t< - composite_accessor_helper::template reduction_t, + composite_accessor_helper::template reduction_t, composite_accessor_impl<>, Ts...>; template struct composite_accessor_merge_traits; @@ -555,8 +556,10 @@ struct facade_conv_traits_impl : applicable_traits { (conv_traits::template applicable_ptr

&& ...); }; template -struct facade_refl_traits_impl { - using refl_meta = composite_meta...>; +struct facade_refl_traits_impl : inapplicable_traits {}; +template requires(refl_traits::applicable && ...) +struct facade_refl_traits_impl : applicable_traits { + using refl_meta = composite_meta::meta...>; using refl_indirect_accessor = composite_accessor; using refl_direct_accessor = composite_accessor; @@ -575,7 +578,9 @@ template is_tuple_like_well_formed() && instantiated_t ::applicable && - is_tuple_like_well_formed()) + is_tuple_like_well_formed() && + instantiated_t + ::applicable) struct facade_traits : instantiated_t, instantiated_t { @@ -596,8 +601,6 @@ struct facade_traits using direct_accessor = merged_composite_accessor< typename facade_traits::conv_direct_accessor, typename facade_traits::refl_direct_accessor>; - static constexpr bool has_indirection = !std::is_same_v< - typename facade_traits::indirect_accessor, composite_accessor_impl<>>; }; using ptr_prototype = void*[2]; @@ -657,14 +660,13 @@ struct proxy_helper { assert(p.has_value()); return *p.meta_.operator->(); } - template + template static decltype(auto) invoke(add_qualifier_t, Q> p, Args&&... args) { auto dispatcher = get_meta(p) .template dispatcher_meta - ::template meta_provider> - ::dispatcher; - if constexpr (C::is_direct && - overload_traits::qualifier == qualifier_type::rv) { + ::template meta_provider>::dispatcher; + if constexpr ( + IsDirect && overload_traits::qualifier == qualifier_type::rv) { meta_ptr_reset_guard guard{p.meta_}; return dispatcher(std::forward>(*p.ptr_), std::forward(args)...); @@ -735,7 +737,8 @@ concept proxiable = facade && sizeof(P) <= F::constraints.max_size && details::facade_traits::template refl_applicable_ptr

; template struct proxy_indirect_accessor {}; -template requires(details::facade_traits::has_indirection) +template requires(!std::is_same_v + ::indirect_accessor, details::composite_accessor_impl<>>) struct proxy_indirect_accessor : details::facade_traits::indirect_accessor {}; @@ -748,20 +751,18 @@ class proxy : public details::facade_traits::direct_accessor { public: proxy() noexcept { ___PRO_DEBUG( - if constexpr (_Traits::has_indirection) { - std::ignore = static_cast* - (proxy::*)() noexcept>(&proxy::operator->); - std::ignore = static_cast* - (proxy::*)() const noexcept>(&proxy::operator->); - std::ignore = static_cast& - (proxy::*)() & noexcept>(&proxy::operator*); - std::ignore = static_cast& - (proxy::*)() const& noexcept>(&proxy::operator*); - std::ignore = static_cast&& (proxy::*)() - && noexcept>(&proxy::operator*); - std::ignore = static_cast&& - (proxy::*)() const&& noexcept>(&proxy::operator*); - } + std::ignore = static_cast* + (proxy::*)() noexcept>(&proxy::operator->); + std::ignore = static_cast* + (proxy::*)() const noexcept>(&proxy::operator->); + std::ignore = static_cast& + (proxy::*)() & noexcept>(&proxy::operator*); + std::ignore = static_cast& + (proxy::*)() const& noexcept>(&proxy::operator*); + std::ignore = static_cast&& + (proxy::*)() && noexcept>(&proxy::operator*); + std::ignore = static_cast&& + (proxy::*)() const&& noexcept>(&proxy::operator*); ) } proxy(std::nullptr_t) noexcept : proxy() {} @@ -913,18 +914,14 @@ class proxy : public details::facade_traits::direct_accessor { F::constraints.destructibility >= constraint_level::nontrivial) { reset(); return initialize

(il, std::forward(args)...); } proxy_indirect_accessor* operator->() noexcept - requires(_Traits::has_indirection) { return std::addressof(ia_); } + { return std::addressof(ia_); } const proxy_indirect_accessor* operator->() const noexcept - requires(_Traits::has_indirection) { return std::addressof(ia_); } - proxy_indirect_accessor& operator*() & noexcept - requires(_Traits::has_indirection) { return ia_; } - const proxy_indirect_accessor& operator*() const& noexcept - requires(_Traits::has_indirection) { return ia_; } + { return std::addressof(ia_); } + proxy_indirect_accessor& operator*() & noexcept { return ia_; } + const proxy_indirect_accessor& operator*() const& noexcept { return ia_; } proxy_indirect_accessor&& operator*() && noexcept - requires(_Traits::has_indirection) - { return std::forward>(ia_); } + { return std::move(ia_); } const proxy_indirect_accessor&& operator*() const&& noexcept - requires(_Traits::has_indirection) { return std::forward>(ia_); } friend void swap(proxy& lhs, proxy& rhs) noexcept(noexcept(lhs.swap(rhs))) @@ -949,32 +946,36 @@ class proxy : public details::facade_traits::direct_accessor { alignas(F::constraints.max_align) std::byte ptr_[F::constraints.max_size]; }; -template -decltype(auto) proxy_invoke(proxy& p, Args&&... args) { - return details::proxy_helper::template invoke< - C, O, details::qualifier_type::lv>(p, std::forward(args)...); +template +auto proxy_invoke(proxy& p, Args&&... args) + -> typename details::overload_traits::return_type { + return details::proxy_helper::template invoke(p, std::forward(args)...); } -template -decltype(auto) proxy_invoke(const proxy& p, Args&&... args) { - return details::proxy_helper::template invoke< - C, O, details::qualifier_type::const_lv>(p, std::forward(args)...); +template +auto proxy_invoke(const proxy& p, Args&&... args) + -> typename details::overload_traits::return_type { + return details::proxy_helper::template invoke(p, std::forward(args)...); } -template -decltype(auto) proxy_invoke(proxy&& p, Args&&... args) { +template +auto proxy_invoke(proxy&& p, Args&&... args) + -> typename details::overload_traits::return_type { return details::proxy_helper::template invoke< - C, O, details::qualifier_type::rv>( - std::forward>(p), std::forward(args)...); + IsDirect, D, O, details::qualifier_type::rv>( + std::move(p), std::forward(args)...); } -template -decltype(auto) proxy_invoke(const proxy&& p, Args&&... args) { +template +auto proxy_invoke(const proxy&& p, Args&&... args) + -> typename details::overload_traits::return_type { return details::proxy_helper::template invoke< - C, O, details::qualifier_type::const_rv>( - std::forward>(p), std::forward(args)...); + IsDirect, D, O, details::qualifier_type::const_rv>( + std::move(p), std::forward(args)...); } -template -const auto& proxy_reflect(const proxy& p) noexcept { - return static_cast&>( +template +const R& proxy_reflect(const proxy& p) noexcept { + return static_cast&>( details::proxy_helper::get_meta(p)).reflector; } @@ -1197,13 +1198,14 @@ using proxy_view = proxy>; { return __VA_ARGS__; } #define ___PRO_DEF_MEM_ACCESSOR_TEMPLATE(__MACRO, ...) \ - template \ + template \ struct ___PRO_ENFORCE_EBO accessor { accessor() = delete; }; \ - template \ - requires(sizeof...(__Os) > 1u && \ - (::std::is_constructible_v> && ...)) \ - struct accessor<__F, __C, __Os...> : accessor<__F, __C, __Os>... \ - { using accessor<__F, __C, __Os>::__VA_ARGS__...; }; \ + template \ + 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__); \ @@ -1221,14 +1223,15 @@ using proxy_view = proxy>; __MACRO(const&& noexcept, ::pro::access_proxy<__F>( \ ::std::forward(*this)), __VA_ARGS__); -#define ___PRO_ADL_ARG ::pro::details::adl_accessor_arg_t<__F, __C> +#define ___PRO_ADL_ARG ::pro::details::adl_accessor_arg_t<__F, __IsDirect> #define ___PRO_DEF_FREE_ACCESSOR_TEMPLATE(__MACRO, ...) \ - template \ + template \ struct ___PRO_ENFORCE_EBO accessor { accessor() = delete; }; \ - template \ - requires(sizeof...(__Os) > 1u && \ - (::std::is_constructible_v> && ...)) \ - struct accessor<__F, __C, __Os...> : accessor<__F, __C, __Os>... {}; \ + template \ + 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, \ @@ -1270,19 +1273,19 @@ class bad_proxy_cast : public std::bad_cast { namespace details { -template +template using adl_accessor_arg_t = - std::conditional_t, proxy_indirect_accessor>; + std::conditional_t, proxy_indirect_accessor>; #define ___PRO_DEF_CAST_ACCESSOR(Q, SELF, ...) \ - template \ - struct accessor<__F, __C, T() Q> { \ + template \ + 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<__C, T() Q>(SELF); \ + return proxy_invoke<__IsDirect, __D, T() Q>(SELF); \ } \ } template @@ -1362,20 +1365,31 @@ 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 +template +struct accessor_instantiation_traits : std::type_identity {}; +template +struct accessor_instantiation_traits>, T, F, IsDirect, Args...> + : std::type_identity> {}; +template +using instantiated_accessor_t = + typename accessor_instantiation_traits::type; + +template struct conv_impl { - static constexpr bool is_direct = IS_DIRECT; + static constexpr bool is_direct = IsDirect; using dispatch_type = D; using overload_types = std::tuple; template - using accessor = accessor_t; + using accessor = instantiated_accessor_t; }; -template +template struct refl_impl { - static constexpr bool is_direct = IS_DIRECT; + static constexpr bool is_direct = IsDirect; using reflector_type = R; template - using accessor = accessor_t; + using accessor = instantiated_accessor_t; }; template struct facade_impl { @@ -1396,9 +1410,9 @@ using merge_tuple_impl_t = recursive_reduction_t; template using merge_tuple_t = instantiated_t; -template +template struct merge_conv_traits - { template using type = conv_impl; }; + { template using type = conv_impl; }; template using merge_conv_t = instantiated_t< merge_conv_traits::template type, @@ -1465,7 +1479,7 @@ template struct facade_of_traits> : std::type_identity {}; template using facade_of_t = typename facade_of_traits

::type; -template +template struct observer_overload_mapping_traits_impl : std::type_identity::view_type> {}; template @@ -1473,13 +1487,13 @@ template std::is_same_v::return_type, proxy_view>) struct observer_overload_mapping_traits_impl : std::type_identity {}; -template +template struct observer_overload_mapping_traits : std::type_identity {}; -template +template requires(overload_traits::qualifier == (std::is_const_v ? qualifier_type::const_lv : qualifier_type::lv)) -struct observer_overload_mapping_traits - : observer_overload_mapping_traits_impl {}; +struct observer_overload_mapping_traits + : observer_overload_mapping_traits_impl {}; template struct observer_overload_mapping_traits : std::type_identity, @@ -1495,11 +1509,10 @@ struct observer_dispatch_reduction template struct observer_overload_ignore_void_reduction : std::type_identity {}; -template +template requires(!std::is_void_v) -struct observer_overload_ignore_void_reduction< - conv_impl, O> - : std::type_identity> {}; +struct observer_overload_ignore_void_reduction, O> + : std::type_identity> {}; template using observer_overload_ignore_void_reduction_t = typename observer_overload_ignore_void_reduction::type; @@ -1570,10 +1583,11 @@ struct proxy_cast_context { void* result_ptr; }; -template +struct proxy_cast_dispatch; +template struct proxy_cast_accessor_impl { - using _Self = - add_qualifier_t, overload_traits::qualifier>; + using _Self = add_qualifier_t< + adl_accessor_arg_t, overload_traits::qualifier>; template friend T proxy_cast(_Self self) { static_assert(!std::is_rvalue_reference_v); @@ -1583,14 +1597,16 @@ struct proxy_cast_accessor_impl { void* result = nullptr; proxy_cast_context ctx{.type_ptr = &typeid(T), .is_ref = true, .is_const = std::is_const_v, .result_ptr = &result}; - proxy_invoke(access_proxy(std::forward<_Self>(self)), ctx); + proxy_invoke( + access_proxy(std::forward<_Self>(self)), ctx); if (result == nullptr) { ___PRO_THROW(bad_proxy_cast{}); } return *static_cast(result); } else { std::optional> result; proxy_cast_context ctx{.type_ptr = &typeid(T), .is_ref = false, .is_const = false, .result_ptr = &result}; - proxy_invoke(access_proxy(std::forward<_Self>(self)), ctx); + proxy_invoke( + access_proxy(std::forward<_Self>(self)), ctx); if (!result.has_value()) { ___PRO_THROW(bad_proxy_cast{}); } return std::move(*result); } @@ -1602,15 +1618,16 @@ struct proxy_cast_accessor_impl { void* result = nullptr; proxy_cast_context ctx{.type_ptr = &typeid(T), .is_ref = true, .is_const = std::is_const_v, .result_ptr = &result}; - proxy_invoke(access_proxy(*self), ctx); + proxy_invoke(access_proxy(*self), ctx); return static_cast(result); } }; #define ___PRO_DEF_PROXY_CAST_ACCESSOR(Q, ...) \ - template \ - struct accessor \ - : proxy_cast_accessor_impl {} + template \ + struct accessor \ + : proxy_cast_accessor_impl {} struct proxy_cast_dispatch { template void operator()(T&& self, proxy_cast_context ctx) { @@ -1639,13 +1656,13 @@ struct proxy_typeid_reflector { : info(&typeid(T)) {} constexpr proxy_typeid_reflector(const proxy_typeid_reflector&) = default; - template + template struct accessor { friend const std::type_info& proxy_typeid( - const adl_accessor_arg_t& self) noexcept { + const adl_accessor_arg_t& self) noexcept { const proxy& p = access_proxy(self); if (!p.has_value()) { return typeid(void); } - const proxy_typeid_reflector& refl = proxy_reflect(p); + const proxy_typeid_reflector& refl = proxy_reflect(p); return *refl.info; } ___PRO_DEBUG( @@ -1653,7 +1670,7 @@ ___PRO_DEBUG( private: static inline const std::type_info& _symbol_guard( - const adl_accessor_arg_t& self) noexcept + const adl_accessor_arg_t& self) noexcept { return proxy_typeid(self); } ) }; @@ -1769,17 +1786,17 @@ template struct operator_dispatch; #define ___PRO_DEF_LHS_LEFT_OP_ACCESSOR(Q, SELF, ...) \ - template \ - struct accessor<__F, __C, R() Q> { \ + template \ + struct accessor<__F, __IsDirect, __D, R() Q> { \ ___PRO_GEN_DEBUG_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \ - R __VA_ARGS__() Q { return proxy_invoke<__C, R() Q>(SELF); } \ + R __VA_ARGS__() Q { return proxy_invoke<__IsDirect, __D, R() Q>(SELF); } \ } #define ___PRO_DEF_LHS_ANY_OP_ACCESSOR(Q, SELF, ...) \ - template \ - struct accessor<__F, __C, R(Args...) Q> { \ + template \ + 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<__C, R(Args...) Q>( \ + return proxy_invoke<__IsDirect, __D, R(Args...) Q>( \ SELF, std::forward(args)...); \ } \ } @@ -1814,10 +1831,11 @@ struct operator_dispatch; }; #define ___PRO_DEF_RHS_OP_ACCESSOR(Q, NE, SELF_ARG, SELF, ...) \ - template \ - struct accessor<__F, __C, R(Arg) Q> { \ + template \ + struct accessor<__F, __IsDirect, __D, R(Arg) Q> { \ friend R operator __VA_ARGS__(Arg arg, SELF_ARG) NE { \ - return proxy_invoke<__C, R(Arg) Q>(SELF, std::forward(arg)); \ + return proxy_invoke<__IsDirect, __D, R(Arg) Q>( \ + SELF, std::forward(arg)); \ } \ ___PRO_DEBUG( \ accessor() noexcept { std::ignore = &accessor::_symbol_guard; } \ @@ -1849,12 +1867,12 @@ ___PRO_DEBUG( \ ___PRO_RHS_OP_DISPATCH_IMPL(__VA_ARGS__) #define ___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR(Q, SELF, ...) \ - template \ - struct accessor<__F, __C, R(Arg) Q> { \ + template \ + 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<__C, R(Arg) Q>(SELF, std::forward(arg)); \ - if constexpr (__C::is_direct) { \ + proxy_invoke<__IsDirect, __D, R(Arg) Q>(SELF, std::forward(arg)); \ + if constexpr (__IsDirect) { \ return SELF; \ } else { \ return *SELF; \ @@ -1862,10 +1880,10 @@ ___PRO_DEBUG( \ } \ } #define ___PRO_DEF_RHS_ASSIGNMENT_OP_ACCESSOR(Q, NE, SELF_ARG, SELF, ...) \ - template \ - struct accessor<__F, __C, R(Arg&) Q> { \ + template \ + struct accessor<__F, __IsDirect, __D, R(Arg&) Q> { \ friend Arg& operator __VA_ARGS__(Arg& arg, SELF_ARG) NE { \ - proxy_invoke<__C, R(Arg&) Q>(SELF, arg); \ + proxy_invoke<__IsDirect, __D, R(Arg&) Q>(SELF, arg); \ return arg; \ } \ ___PRO_DEBUG( \ @@ -2007,11 +2025,12 @@ struct weak_dispatch : D { __MACRO, __VA_ARGS__, 3, 2)(__VA_ARGS__)) #define ___PRO_DEF_MEM_ACCESSOR(__Q, __SELF, ...) \ - template \ - struct accessor<__F, __C, __R(__Args...) __Q> { \ + template \ + 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<__C, __R(__Args...) __Q>( \ + return ::pro::proxy_invoke<__IsDirect, __D, __R(__Args...) __Q>( \ __SELF, ::std::forward<__Args>(__args)...); \ } \ } @@ -2031,10 +2050,11 @@ struct weak_dispatch : D { ___PRO_EXPAND_MACRO(___PRO_DEF_MEM_DISPATCH, __NAME, __VA_ARGS__) #define ___PRO_DEF_FREE_ACCESSOR(__Q, __NE, __SELF_ARG, __SELF, ...) \ - template \ - struct accessor<__F, __C, __R(__Args...) __Q> { \ + template \ + struct accessor<__F, __IsDirect, __D, __R(__Args...) __Q> { \ friend __R __VA_ARGS__(__SELF_ARG, __Args... __args) __NE { \ - return ::pro::proxy_invoke<__C, __R(__Args...) __Q>( \ + return ::pro::proxy_invoke<__IsDirect, __D, __R(__Args...) __Q>( \ __SELF, ::std::forward<__Args>(__args)...); \ } \ ___PRO_DEBUG( \ diff --git a/samples/access_proxy.cpp b/samples/access_proxy.cpp index 7beaea3..5ca136d 100644 --- a/samples/access_proxy.cpp +++ b/samples/access_proxy.cpp @@ -20,13 +20,12 @@ int main() { std::cout << ToString(*p) << "\n"; // Prints: "123" // How it works behind the scenes - using Convention = std::tuple_element_t<0u, Stringable::convention_types>; - using Accessor = Convention::accessor; + using Accessor = FreeToString::accessor; static_assert(std::is_base_of_v>); Accessor& a = static_cast(*p); pro::proxy& p2 = pro::access_proxy(a); std::cout << std::boolalpha << (&p == &p2) << "\n"; // Prints: "true" because access_proxy converts // an accessor back to the original proxy - auto result = pro::proxy_invoke(p2); + auto result = pro::proxy_invoke(p2); std::cout << result << "\n"; // Prints: "123" } diff --git a/samples/basic_facade_builder/add_reflection.cpp b/samples/basic_facade_builder/add_reflection.cpp index 4823729..ffd8dff 100644 --- a/samples/basic_facade_builder/add_reflection.cpp +++ b/samples/basic_facade_builder/add_reflection.cpp @@ -12,10 +12,10 @@ class RttiReflector { template constexpr explicit RttiReflector(std::in_place_type_t) : type_(typeid(T)) {} - template + template struct accessor { const char* GetTypeName() const noexcept { - const RttiReflector& self = pro::proxy_reflect(pro::access_proxy(*this)); + const RttiReflector& self = pro::proxy_reflect(pro::access_proxy(*this)); return self.type_.name(); } }; diff --git a/samples/proxy_invoke.cpp b/samples/proxy_invoke.cpp index 44197c2..9da35ae 100644 --- a/samples/proxy_invoke.cpp +++ b/samples/proxy_invoke.cpp @@ -17,7 +17,5 @@ int main() { int a = 123; pro::proxy p = &a; std::cout << ToString(*p) << "\n"; // Invokes with accessor, prints: "123" - - using C = std::tuple_element_t<0u, Stringable::convention_types>; - std::cout << pro::proxy_invoke(p) << "\n"; // Invokes with proxy_invoke, also prints: "123" + std::cout << pro::proxy_invoke(p) << "\n"; // Invokes with proxy_invoke, also prints: "123" } diff --git a/samples/proxy_reflect.cpp b/samples/proxy_reflect.cpp index 1f17e4c..c9d254b 100644 --- a/samples/proxy_reflect.cpp +++ b/samples/proxy_reflect.cpp @@ -14,10 +14,10 @@ class CopyabilityReflector { constexpr explicit CopyabilityReflector(std::in_place_type_t) : copyable_(std::is_copy_constructible_v) {} - template + template struct accessor { bool IsCopyable() const noexcept { - const CopyabilityReflector& self = pro::proxy_reflect(pro::access_proxy(*this)); + const CopyabilityReflector& self = pro::proxy_reflect(pro::access_proxy(*this)); return self.copyable_; } }; diff --git a/tests/proxy_creation_tests.cpp b/tests/proxy_creation_tests.cpp index 16e5a80..dcc95fe 100644 --- a/tests/proxy_creation_tests.cpp +++ b/tests/proxy_creation_tests.cpp @@ -20,10 +20,10 @@ struct SboReflector { constexpr explicit SboReflector(std::in_place_type_t>) : SboEnabled(false), AllocatorAllocatesForItself(true) {} - template + template struct accessor { const SboReflector& ReflectSbo() const noexcept { - return pro::proxy_reflect(pro::access_proxy(*this)); + return pro::proxy_reflect(pro::access_proxy(*this)); } }; diff --git a/tests/proxy_reflection_tests.cpp b/tests/proxy_reflection_tests.cpp index 232638e..e4c157a 100644 --- a/tests/proxy_reflection_tests.cpp +++ b/tests/proxy_reflection_tests.cpp @@ -19,10 +19,10 @@ struct TraitsReflector { is_nothrow_destructible_(std::is_nothrow_destructible_v), is_trivial_(std::is_trivial_v) {} - template + template struct accessor { const TraitsReflector& ReflectTraits() const noexcept { - return pro::proxy_reflect(pro::access_proxy(*this)); + return pro::proxy_reflect(pro::access_proxy(*this)); } }; diff --git a/tests/proxy_traits_tests.cpp b/tests/proxy_traits_tests.cpp index 0897a3e..0bdd7dc 100644 --- a/tests/proxy_traits_tests.cpp +++ b/tests/proxy_traits_tests.cpp @@ -298,7 +298,7 @@ struct BadFacade_BadReflectionType { .destructibility = pro::constraint_level::nothrow, }; }; -static_assert(pro::facade); +static_assert(!pro::facade); PRO_DEF_MEM_DISPATCH(MemFoo, Foo); PRO_DEF_MEM_DISPATCH(MemBar, Bar); diff --git a/tests/utils.h b/tests/utils.h index c6d6292..1ae4ba0 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -97,10 +97,10 @@ class RttiReflector { template constexpr explicit RttiReflector(std::in_place_type_t) : type_(typeid(T)) {} - template + template struct accessor { const char* GetTypeName() const noexcept { - const RttiReflector& self = pro::proxy_reflect(pro::access_proxy(*this)); + const RttiReflector& self = pro::proxy_reflect(pro::access_proxy(*this)); return self.type_.name(); } };