Skip to content

Commit

Permalink
Merge branch 'main' into user/mingxwa/refactor-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mingxwa authored Nov 19, 2024
2 parents 42e18c1 + b172bae commit c81902a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 24 deletions.
2 changes: 1 addition & 1 deletion docs/ProAccessible.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Given that `F` is a type meeting the [*ProBasicFacade* requirements](ProBasicFac

| Expressions | Semantics |
| ------------------------------------------- | ------------------------------------------------------------ |
| `typename T::template accessor<F, Args...>` | A type that provides accessibility to `proxy`. It shall be a trivial class type and not [final](https://en.cppreference.com/w/cpp/language/final). |
| `typename T::template accessor<F, 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

Expand Down
85 changes: 62 additions & 23 deletions proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,30 +450,37 @@ struct lifetime_meta_traits<MP, constraint_level::nontrivial>
template <template <bool> class MP, constraint_level C>
using lifetime_meta_t = typename lifetime_meta_traits<MP, C>::type;

template <class F> struct proxy_indirect_accessor;
template <class... As>
class ___PRO_ENFORCE_EBO composite_accessor_impl : public As... {
template <class> friend class pro::proxy;
template <class F> friend struct 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... Args>
struct sfinae_accessor_traits : std::type_identity<void> {};
template <class T, class... Args>
struct sfinae_accessor_traits<
std::void_t<typename T::template accessor<Args...>>, T, Args...>
: std::type_identity<typename T::template accessor<Args...>> {};
: accessor_traits_impl<typename T::template accessor<Args...>> {};
template <class T, class... Args>
using accessor_t = typename sfinae_accessor_traits<void, T, Args...>::type;

template <bool IS_DIRECT, class F, class O, class I>
struct composite_accessor_reduction : std::type_identity<O> {};
template <bool IS_DIRECT, class F, class... As, class I>
requires(IS_DIRECT == I::is_direct && std::is_trivial_v<accessor_t<I, F>> &&
!std::is_final_v<accessor_t<I, F>>)
requires(IS_DIRECT == I::is_direct && !std::is_void_v<accessor_t<I, F>>)
struct composite_accessor_reduction<
IS_DIRECT, F, composite_accessor_impl<As...>, I>
{ using type = composite_accessor_impl<As..., accessor_t<I, F>>; };
Expand Down Expand Up @@ -508,7 +515,6 @@ consteval bool is_facade_constraints_well_formed() {
}
return false;
}
struct empty_proxy_base {};
template <class F, class... Cs>
struct facade_conv_traits_impl : inapplicable_traits {};
template <class F, class... Cs> requires(conv_traits<Cs>::applicable && ...)
Expand Down Expand Up @@ -563,12 +569,14 @@ struct facade_traits<F>
using direct_accessor = merged_composite_accessor<
typename facade_traits::conv_direct_accessor,
typename facade_traits::refl_direct_accessor>;
using base = std::conditional_t<std::is_same_v<direct_accessor,
composite_accessor_impl<>>, empty_proxy_base, direct_accessor>;
static constexpr bool has_indirection = !std::is_same_v<
typename facade_traits::indirect_accessor, composite_accessor_impl<>>;
};

template <class F> struct proxy_indirect_accessor {};
template <class F> requires(facade_traits<F>::has_indirection)
struct proxy_indirect_accessor<F> : facade_traits<F>::indirect_accessor {};

using ptr_prototype = void*[2];

template <class M>
Expand Down Expand Up @@ -672,14 +680,32 @@ concept proxiable = facade<F> && sizeof(P) <= F::constraints.max_size &&
details::facade_traits<F>::template refl_applicable_ptr<P>;

template <class F>
class proxy : public details::facade_traits<F>::base {
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>;
using _IA = details::proxy_indirect_accessor<F>;

public:
#ifdef NDEBUG
proxy() noexcept = default;
proxy(std::nullptr_t) noexcept {}
#else
proxy() noexcept {
if constexpr (_Traits::has_indirection) {
std::ignore = static_cast<_IA* (proxy::*)() noexcept>(&proxy::operator->);
std::ignore = static_cast<const _IA* (proxy::*)() const noexcept>(
&proxy::operator->);
std::ignore = static_cast<_IA& (proxy::*)() & noexcept>(&proxy::operator*);
std::ignore = static_cast<const _IA& (proxy::*)() const& noexcept>(
&proxy::operator*);
std::ignore = static_cast<_IA&& (proxy::*)() && noexcept>(
&proxy::operator*);
std::ignore = static_cast<const _IA&& (proxy::*)() const&& noexcept>(
&proxy::operator*);
}
}
#endif // NDEBUG
proxy(std::nullptr_t) noexcept : proxy() {}
proxy(const proxy&) noexcept requires(F::constraints.copyability ==
constraint_level::trivial) = default;
proxy(const proxy& rhs)
Expand Down Expand Up @@ -709,20 +735,20 @@ class proxy : public details::facade_traits<F>::base {
template <class P>
proxy(P&& ptr) noexcept(std::is_nothrow_constructible_v<std::decay_t<P>, P>)
requires(proxiable<std::decay_t<P>, F> &&
std::is_constructible_v<std::decay_t<P>, P>)
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...>)
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...>)
{ initialize<P>(il, std::forward<Args>(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)
Expand Down Expand Up @@ -826,18 +852,18 @@ class proxy : public details::facade_traits<F>::base {
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)...); }
auto operator->() noexcept requires(_Traits::has_indirection)
_IA* operator->() noexcept requires(_Traits::has_indirection)
{ return std::addressof(ia_); }
auto operator->() const noexcept requires(_Traits::has_indirection)
const _IA* operator->() const noexcept requires(_Traits::has_indirection)
{ return std::addressof(ia_); }
auto& operator*() & noexcept requires(_Traits::has_indirection)
_IA& operator*() & noexcept requires(_Traits::has_indirection)
{ return ia_; }
auto& operator*() const& noexcept requires(_Traits::has_indirection)
const _IA& operator*() const& noexcept requires(_Traits::has_indirection)
{ return ia_; }
auto&& operator*() && noexcept requires(_Traits::has_indirection)
{ return std::forward<typename _Traits::indirect_accessor>(ia_); }
auto&& operator*() const&& noexcept requires(_Traits::has_indirection)
{ return std::forward<const typename _Traits::indirect_accessor>(ia_); }
_IA&& operator*() && noexcept requires(_Traits::has_indirection)
{ return std::forward<_IA>(ia_); }
const _IA&& operator*() const&& noexcept requires(_Traits::has_indirection)
{ return std::forward<const _IA>(ia_); }

friend void swap(proxy& lhs, proxy& rhs) noexcept(noexcept(lhs.swap(rhs)))
{ lhs.swap(rhs); }
Expand All @@ -856,7 +882,7 @@ class proxy : public details::facade_traits<F>::base {
}

[[___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE]]
typename _Traits::indirect_accessor ia_;
_IA ia_;
details::meta_ptr<typename _Traits::meta> meta_;
alignas(F::constraints.max_align) std::byte ptr_[F::constraints.max_size];
};
Expand Down Expand Up @@ -1107,9 +1133,9 @@ proxy<F> make_proxy(T&& value) {
struct ___PRO_ENFORCE_EBO accessor { accessor() = delete; }; \
template <class __F, class __C, class... __Os> \
requires(sizeof...(__Os) > 1u && \
(::std::is_trivial_v<accessor<__F, __C, __Os>> && ...)) \
(::std::is_constructible_v<accessor<__F, __C, __Os>> && ...)) \
struct accessor<__F, __C, __Os...> : accessor<__F, __C, __Os>... \
{ using accessor<__F, __C, __Os>:: __VA_ARGS__ ...; }; \
{ using accessor<__F, __C, __Os>::__VA_ARGS__...; }; \
__MACRO(, *this, __VA_ARGS__); \
__MACRO(noexcept, *this, __VA_ARGS__); \
__MACRO(&, *this, __VA_ARGS__); \
Expand All @@ -1129,7 +1155,7 @@ proxy<F> make_proxy(T&& value) {
struct ___PRO_ENFORCE_EBO accessor { accessor() = delete; }; \
template <class __F, class __C, class... __Os> \
requires(sizeof...(__Os) > 1u && \
(::std::is_trivial_v<accessor<__F, __C, __Os>> && ...)) \
(::std::is_constructible_v<accessor<__F, __C, __Os>> && ...)) \
struct accessor<__F, __C, __Os...> : accessor<__F, __C, __Os>... {}; \
__MACRO(,, accessor& __self, __self, __VA_ARGS__); \
__MACRO(noexcept, noexcept, accessor& __self, __self, __VA_ARGS__); \
Expand All @@ -1150,6 +1176,13 @@ proxy<F> make_proxy(T&& value) {
__MACRO(const&& noexcept, noexcept, const accessor&& __self, \
::std::forward<const accessor>(__self), __VA_ARGS__);

#ifdef NDEBUG
#define ___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR(...)
#else
#define ___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR(...) \
accessor() noexcept { ::std::ignore = &accessor::__VA_ARGS__; }
#endif // NDEBUG

namespace details {

constexpr std::size_t invalid_size = std::numeric_limits<std::size_t>::max();
Expand Down Expand Up @@ -1227,6 +1260,7 @@ struct facade_impl {
#define ___PRO_DEF_UPWARD_CONVERSION_ACCESSOR(Q, SELF, ...) \
template <class F2, class C> \
struct accessor<F2, C, proxy<F>() Q> { \
___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
__VA_ARGS__ () Q { \
if (access_proxy<F2>(SELF).has_value()) { \
return proxy_invoke<C, proxy<F>() Q>(access_proxy<F2>(SELF)); \
Expand Down Expand Up @@ -1389,12 +1423,14 @@ struct operator_dispatch;
#define ___PRO_DEF_LHS_LEFT_OP_ACCESSOR(Q, SELF, ...) \
template <class F, class C, class R> \
struct accessor<F, C, R() Q> { \
___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
R __VA_ARGS__ () Q \
{ return proxy_invoke<C, R() Q>(access_proxy<F>(SELF)); } \
}
#define ___PRO_DEF_LHS_ANY_OP_ACCESSOR(Q, SELF, ...) \
template <class F, class C, class R, class... Args> \
struct accessor<F, C, R(Args...) Q> { \
___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
R __VA_ARGS__ (Args... args) Q { \
return proxy_invoke<C, R(Args...) Q>( \
access_proxy<F>(SELF), std::forward<Args>(args)...); \
Expand Down Expand Up @@ -1460,6 +1496,7 @@ struct operator_dispatch;
#define ___PRO_DEF_LHS_ASSIGNMENT_OP_ACCESSOR(Q, SELF, ...) \
template <class F, class C, class R, class Arg> \
struct accessor<F, C, R(Arg) Q> { \
___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
decltype(auto) __VA_ARGS__ (Arg arg) Q { \
proxy_invoke<C, R(Arg) Q>( \
access_proxy<F>(SELF), std::forward<Arg>(arg)); \
Expand Down Expand Up @@ -1577,6 +1614,7 @@ struct operator_dispatch<"[]", false> {
#define ___PRO_DEF_CONVERSION_ACCESSOR(Q, SELF, ...) \
template <class F, class C> \
struct accessor<F, C, T() Q> { \
___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
explicit(Expl) __VA_ARGS__ () Q \
{ return proxy_invoke<C, T() Q>(access_proxy<F>(SELF)); } \
}
Expand Down Expand Up @@ -1604,6 +1642,7 @@ struct conversion_dispatch {
#define ___PRO_DEF_MEM_ACCESSOR(__Q, __SELF, ...) \
template <class __F, class __C, class __R, class... __Args> \
struct accessor<__F, __C, __R(__Args...) __Q> { \
___PRO_GEN_SYMBOL_FOR_MEM_ACCESSOR(__VA_ARGS__) \
__R __VA_ARGS__ (__Args... __args) __Q { \
return ::pro::proxy_invoke<__C, __R(__Args...) __Q>( \
::pro::access_proxy<__F>(__SELF), \
Expand Down

0 comments on commit c81902a

Please sign in to comment.