Add friendship support to prefer CPO.

This commit is contained in:
Christopher Kohlhoff 2021-01-06 12:04:24 +11:00
parent 11f7ae1fab
commit a3992b6d8e

View File

@ -118,6 +118,7 @@ struct prefer_result
namespace asio_prefer_fn {
using asio::conditional;
using asio::decay;
using asio::declval;
using asio::enable_if;
@ -143,8 +144,8 @@ enum overload_type
ill_formed
};
template <typename T, typename Properties, typename = void,
typename = void, typename = void, typename = void,
template <typename Impl, typename T, typename Properties,
typename = void, typename = void, typename = void, typename = void,
typename = void, typename = void, typename = void>
struct call_traits
{
@ -153,8 +154,8 @@ struct call_traits
typedef void result_type;
};
template <typename T, typename Property>
struct call_traits<T, void(Property),
template <typename Impl, typename T, typename Property>
struct call_traits<Impl, T, void(Property),
typename enable_if<
is_applicable_property<
typename decay<T>::type,
@ -178,8 +179,8 @@ struct call_traits<T, void(Property),
#endif // defined(ASIO_HAS_MOVE)
};
template <typename T, typename Property>
struct call_traits<T, void(Property),
template <typename Impl, typename T, typename Property>
struct call_traits<Impl, T, void(Property),
typename enable_if<
is_applicable_property<
typename decay<T>::type,
@ -193,15 +194,15 @@ struct call_traits<T, void(Property),
!static_require<T, Property>::is_valid
>::type,
typename enable_if<
require_member<T, Property>::is_valid
require_member<typename Impl::template proxy<T>::type, Property>::is_valid
>::type> :
require_member<T, Property>
require_member<typename Impl::template proxy<T>::type, Property>
{
ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_member);
};
template <typename T, typename Property>
struct call_traits<T, void(Property),
template <typename Impl, typename T, typename Property>
struct call_traits<Impl, T, void(Property),
typename enable_if<
is_applicable_property<
typename decay<T>::type,
@ -215,7 +216,7 @@ struct call_traits<T, void(Property),
!static_require<T, Property>::is_valid
>::type,
typename enable_if<
!require_member<T, Property>::is_valid
!require_member<typename Impl::template proxy<T>::type, Property>::is_valid
>::type,
typename enable_if<
require_free<T, Property>::is_valid
@ -225,8 +226,8 @@ struct call_traits<T, void(Property),
ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_free);
};
template <typename T, typename Property>
struct call_traits<T, void(Property),
template <typename Impl, typename T, typename Property>
struct call_traits<Impl, T, void(Property),
typename enable_if<
is_applicable_property<
typename decay<T>::type,
@ -240,21 +241,21 @@ struct call_traits<T, void(Property),
!static_require<T, Property>::is_valid
>::type,
typename enable_if<
!require_member<T, Property>::is_valid
!require_member<typename Impl::template proxy<T>::type, Property>::is_valid
>::type,
typename enable_if<
!require_free<T, Property>::is_valid
>::type,
typename enable_if<
prefer_member<T, Property>::is_valid
prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid
>::type> :
prefer_member<T, Property>
prefer_member<typename Impl::template proxy<T>::type, Property>
{
ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_member);
};
template <typename T, typename Property>
struct call_traits<T, void(Property),
template <typename Impl, typename T, typename Property>
struct call_traits<Impl, T, void(Property),
typename enable_if<
is_applicable_property<
typename decay<T>::type,
@ -268,13 +269,13 @@ struct call_traits<T, void(Property),
!static_require<T, Property>::is_valid
>::type,
typename enable_if<
!require_member<T, Property>::is_valid
!require_member<typename Impl::template proxy<T>::type, Property>::is_valid
>::type,
typename enable_if<
!require_free<T, Property>::is_valid
>::type,
typename enable_if<
!prefer_member<T, Property>::is_valid
!prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid
>::type,
typename enable_if<
prefer_free<T, Property>::is_valid
@ -284,8 +285,8 @@ struct call_traits<T, void(Property),
ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_free);
};
template <typename T, typename Property>
struct call_traits<T, void(Property),
template <typename Impl, typename T, typename Property>
struct call_traits<Impl, T, void(Property),
typename enable_if<
is_applicable_property<
typename decay<T>::type,
@ -299,13 +300,13 @@ struct call_traits<T, void(Property),
!static_require<T, Property>::is_valid
>::type,
typename enable_if<
!require_member<T, Property>::is_valid
!require_member<typename Impl::template proxy<T>::type, Property>::is_valid
>::type,
typename enable_if<
!require_free<T, Property>::is_valid
>::type,
typename enable_if<
!prefer_member<T, Property>::is_valid
!prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid
>::type,
typename enable_if<
!prefer_free<T, Property>::is_valid
@ -321,14 +322,15 @@ struct call_traits<T, void(Property),
#endif // defined(ASIO_HAS_MOVE)
};
template <typename T, typename P0, typename P1>
struct call_traits<T, void(P0, P1),
template <typename Impl, typename T, typename P0, typename P1>
struct call_traits<Impl, T, void(P0, P1),
typename enable_if<
call_traits<T, void(P0)>::overload != ill_formed
call_traits<Impl, T, void(P0)>::overload != ill_formed
>::type,
typename enable_if<
call_traits<
typename call_traits<T, void(P0)>::result_type,
Impl,
typename call_traits<Impl, T, void(P0)>::result_type,
void(P1)
>::overload != ill_formed
>::type>
@ -337,30 +339,34 @@ struct call_traits<T, void(P0, P1),
ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
(
call_traits<T, void(P0)>::is_noexcept
call_traits<Impl, T, void(P0)>::is_noexcept
&&
call_traits<
typename call_traits<T, void(P0)>::result_type,
Impl,
typename call_traits<Impl, T, void(P0)>::result_type,
void(P1)
>::is_noexcept
));
typedef typename decay<
typename call_traits<
typename call_traits<T, void(P0)>::result_type,
Impl,
typename call_traits<Impl, T, void(P0)>::result_type,
void(P1)
>::result_type
>::type result_type;
};
template <typename T, typename P0, typename P1, typename ASIO_ELLIPSIS PN>
struct call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS),
template <typename Impl, typename T, typename P0,
typename P1, typename ASIO_ELLIPSIS PN>
struct call_traits<Impl, T, void(P0, P1, PN ASIO_ELLIPSIS),
typename enable_if<
call_traits<T, void(P0)>::overload != ill_formed
call_traits<Impl, T, void(P0)>::overload != ill_formed
>::type,
typename enable_if<
call_traits<
typename call_traits<T, void(P0)>::result_type,
Impl,
typename call_traits<Impl, T, void(P0)>::result_type,
void(P1, PN ASIO_ELLIPSIS)
>::overload != ill_formed
>::type>
@ -369,17 +375,19 @@ struct call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS),
ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
(
call_traits<T, void(P0)>::is_noexcept
call_traits<Impl, T, void(P0)>::is_noexcept
&&
call_traits<
typename call_traits<T, void(P0)>::result_type,
Impl,
typename call_traits<Impl, T, void(P0)>::result_type,
void(P1, PN ASIO_ELLIPSIS)
>::is_noexcept
));
typedef typename decay<
typename call_traits<
typename call_traits<T, void(P0)>::result_type,
Impl,
typename call_traits<Impl, T, void(P0)>::result_type,
void(P1, PN ASIO_ELLIPSIS)
>::result_type
>::type result_type;
@ -387,30 +395,70 @@ struct call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS),
struct impl
{
template <typename T>
struct proxy
{
#if defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) \
&& defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
struct type
{
template <typename P>
auto require(ASIO_MOVE_ARG(P) p)
noexcept(
noexcept(
declval<typename conditional<true, T, P>::type>().require(
ASIO_MOVE_CAST(P)(p))
)
)
-> decltype(
declval<typename conditional<true, T, P>::type>().require(
ASIO_MOVE_CAST(P)(p))
);
template <typename P>
auto prefer(ASIO_MOVE_ARG(P) p)
noexcept(
noexcept(
declval<typename conditional<true, T, P>::type>().prefer(
ASIO_MOVE_CAST(P)(p))
)
)
-> decltype(
declval<typename conditional<true, T, P>::type>().prefer(
ASIO_MOVE_CAST(P)(p))
);
};
#else // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
// && defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
typedef T type;
#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
// && defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
};
template <typename T, typename Property>
ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
call_traits<T, void(Property)>::overload == identity,
typename call_traits<T, void(Property)>::result_type
call_traits<impl, T, void(Property)>::overload == identity,
typename call_traits<impl, T, void(Property)>::result_type
>::type
operator()(
ASIO_MOVE_ARG(T) t,
ASIO_MOVE_ARG(Property)) const
ASIO_NOEXCEPT_IF((
call_traits<T, void(Property)>::is_noexcept))
call_traits<impl, T, void(Property)>::is_noexcept))
{
return ASIO_MOVE_CAST(T)(t);
}
template <typename T, typename Property>
ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
call_traits<T, void(Property)>::overload == call_require_member,
typename call_traits<T, void(Property)>::result_type
call_traits<impl, T, void(Property)>::overload == call_require_member,
typename call_traits<impl, T, void(Property)>::result_type
>::type
operator()(
ASIO_MOVE_ARG(T) t,
ASIO_MOVE_ARG(Property) p) const
ASIO_NOEXCEPT_IF((
call_traits<T, void(Property)>::is_noexcept))
call_traits<impl, T, void(Property)>::is_noexcept))
{
return ASIO_MOVE_CAST(T)(t).require(
ASIO_MOVE_CAST(Property)(p));
@ -418,14 +466,14 @@ struct impl
template <typename T, typename Property>
ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
call_traits<T, void(Property)>::overload == call_require_free,
typename call_traits<T, void(Property)>::result_type
call_traits<impl, T, void(Property)>::overload == call_require_free,
typename call_traits<impl, T, void(Property)>::result_type
>::type
operator()(
ASIO_MOVE_ARG(T) t,
ASIO_MOVE_ARG(Property) p) const
ASIO_NOEXCEPT_IF((
call_traits<T, void(Property)>::is_noexcept))
call_traits<impl, T, void(Property)>::is_noexcept))
{
return require(
ASIO_MOVE_CAST(T)(t),
@ -434,14 +482,14 @@ struct impl
template <typename T, typename Property>
ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
call_traits<T, void(Property)>::overload == call_prefer_member,
typename call_traits<T, void(Property)>::result_type
call_traits<impl, T, void(Property)>::overload == call_prefer_member,
typename call_traits<impl, T, void(Property)>::result_type
>::type
operator()(
ASIO_MOVE_ARG(T) t,
ASIO_MOVE_ARG(Property) p) const
ASIO_NOEXCEPT_IF((
call_traits<T, void(Property)>::is_noexcept))
call_traits<impl, T, void(Property)>::is_noexcept))
{
return ASIO_MOVE_CAST(T)(t).prefer(
ASIO_MOVE_CAST(Property)(p));
@ -449,14 +497,14 @@ struct impl
template <typename T, typename Property>
ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
call_traits<T, void(Property)>::overload == call_prefer_free,
typename call_traits<T, void(Property)>::result_type
call_traits<impl, T, void(Property)>::overload == call_prefer_free,
typename call_traits<impl, T, void(Property)>::result_type
>::type
operator()(
ASIO_MOVE_ARG(T) t,
ASIO_MOVE_ARG(Property) p) const
ASIO_NOEXCEPT_IF((
call_traits<T, void(Property)>::is_noexcept))
call_traits<impl, T, void(Property)>::is_noexcept))
{
return prefer(
ASIO_MOVE_CAST(T)(t),
@ -465,15 +513,15 @@ struct impl
template <typename T, typename P0, typename P1>
ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
call_traits<T, void(P0, P1)>::overload == two_props,
typename call_traits<T, void(P0, P1)>::result_type
call_traits<impl, T, void(P0, P1)>::overload == two_props,
typename call_traits<impl, T, void(P0, P1)>::result_type
>::type
operator()(
ASIO_MOVE_ARG(T) t,
ASIO_MOVE_ARG(P0) p0,
ASIO_MOVE_ARG(P1) p1) const
ASIO_NOEXCEPT_IF((
call_traits<T, void(P0, P1)>::is_noexcept))
call_traits<impl, T, void(P0, P1)>::is_noexcept))
{
return (*this)(
(*this)(
@ -485,8 +533,10 @@ struct impl
template <typename T, typename P0, typename P1,
typename ASIO_ELLIPSIS PN>
ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props,
typename call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::result_type
call_traits<impl, T,
void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props,
typename call_traits<impl, T,
void(P0, P1, PN ASIO_ELLIPSIS)>::result_type
>::type
operator()(
ASIO_MOVE_ARG(T) t,
@ -494,7 +544,7 @@ struct impl
ASIO_MOVE_ARG(P1) p1,
ASIO_MOVE_ARG(PN) ASIO_ELLIPSIS pn) const
ASIO_NOEXCEPT_IF((
call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept))
call_traits<impl, T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept))
{
return (*this)(
(*this)(
@ -523,13 +573,16 @@ static ASIO_CONSTEXPR const asio_prefer_fn::impl&
} // namespace
typedef asio_prefer_fn::impl prefer_t;
#if defined(ASIO_HAS_VARIADIC_TEMPLATES)
template <typename T, typename... Properties>
struct can_prefer :
integral_constant<bool,
asio_prefer_fn::call_traits<T, void(Properties...)>::overload
!= asio_prefer_fn::ill_formed>
asio_prefer_fn::call_traits<
prefer_t, T, void(Properties...)>::overload
!= asio_prefer_fn::ill_formed>
{
};
@ -539,24 +592,27 @@ template <typename T, typename P0 = void,
typename P1 = void, typename P2 = void>
struct can_prefer :
integral_constant<bool,
asio_prefer_fn::call_traits<T, void(P0, P1, P2)>::overload
!= asio_prefer_fn::ill_formed>
asio_prefer_fn::call_traits<
prefer_t, T, void(P0, P1, P2)>::overload
!= asio_prefer_fn::ill_formed>
{
};
template <typename T, typename P0, typename P1>
struct can_prefer<T, P0, P1> :
integral_constant<bool,
asio_prefer_fn::call_traits<T, void(P0, P1)>::overload
!= asio_prefer_fn::ill_formed>
asio_prefer_fn::call_traits<
prefer_t, T, void(P0, P1)>::overload
!= asio_prefer_fn::ill_formed>
{
};
template <typename T, typename P0>
struct can_prefer<T, P0> :
integral_constant<bool,
asio_prefer_fn::call_traits<T, void(P0)>::overload
!= asio_prefer_fn::ill_formed>
asio_prefer_fn::call_traits<
prefer_t, T, void(P0)>::overload
!= asio_prefer_fn::ill_formed>
{
};
@ -581,7 +637,8 @@ constexpr bool can_prefer_v
template <typename T, typename... Properties>
struct is_nothrow_prefer :
integral_constant<bool,
asio_prefer_fn::call_traits<T, void(Properties...)>::is_noexcept>
asio_prefer_fn::call_traits<
prefer_t, T, void(Properties...)>::is_noexcept>
{
};
@ -591,21 +648,24 @@ template <typename T, typename P0 = void,
typename P1 = void, typename P2 = void>
struct is_nothrow_prefer :
integral_constant<bool,
asio_prefer_fn::call_traits<T, void(P0, P1, P2)>::is_noexcept>
asio_prefer_fn::call_traits<
prefer_t, T, void(P0, P1, P2)>::is_noexcept>
{
};
template <typename T, typename P0, typename P1>
struct is_nothrow_prefer<T, P0, P1> :
integral_constant<bool,
asio_prefer_fn::call_traits<T, void(P0, P1)>::is_noexcept>
asio_prefer_fn::call_traits<
prefer_t, T, void(P0, P1)>::is_noexcept>
{
};
template <typename T, typename P0>
struct is_nothrow_prefer<T, P0> :
integral_constant<bool,
asio_prefer_fn::call_traits<T, void(P0)>::is_noexcept>
asio_prefer_fn::call_traits<
prefer_t, T, void(P0)>::is_noexcept>
{
};
@ -631,7 +691,7 @@ template <typename T, typename... Properties>
struct prefer_result
{
typedef typename asio_prefer_fn::call_traits<
T, void(Properties...)>::result_type type;
prefer_t, T, void(Properties...)>::result_type type;
};
#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
@ -641,21 +701,21 @@ template <typename T, typename P0 = void,
struct prefer_result
{
typedef typename asio_prefer_fn::call_traits<
T, void(P0, P1, P2)>::result_type type;
prefer_t, T, void(P0, P1, P2)>::result_type type;
};
template <typename T, typename P0, typename P1>
struct prefer_result<T, P0, P1>
{
typedef typename asio_prefer_fn::call_traits<
T, void(P0, P1)>::result_type type;
prefer_t, T, void(P0, P1)>::result_type type;
};
template <typename T, typename P0>
struct prefer_result<T, P0>
{
typedef typename asio_prefer_fn::call_traits<
T, void(P0)>::result_type type;
prefer_t, T, void(P0)>::result_type type;
};
template <typename T>