Skip to content

Commit

Permalink
Add friendship support to require_concept CPO.
Browse files Browse the repository at this point in the history
  • Loading branch information
chriskohlhoff committed Jan 6, 2021
1 parent a3992b6 commit 962a85f
Showing 1 changed file with 61 additions and 23 deletions.
84 changes: 61 additions & 23 deletions asio/include/asio/require_concept.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ struct require_concept_result

namespace asio_require_concept_fn {

using asio::conditional;
using asio::decay;
using asio::declval;
using asio::enable_if;
Expand All @@ -125,7 +126,7 @@ enum overload_type
ill_formed
};

template <typename T, typename Properties, typename = void,
template <typename Impl, typename T, typename Properties, typename = void,
typename = void, typename = void, typename = void, typename = void>
struct call_traits
{
Expand All @@ -134,8 +135,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,
Expand All @@ -154,8 +155,8 @@ struct call_traits<T, void(Property),
typedef ASIO_MOVE_ARG(T) 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,
Expand All @@ -169,15 +170,21 @@ struct call_traits<T, void(Property),
!static_require_concept<T, Property>::is_valid
>::type,
typename enable_if<
require_concept_member<T, Property>::is_valid
require_concept_member<
typename Impl::template proxy<T>::type,
Property
>::is_valid
>::type> :
require_concept_member<T, Property>
require_concept_member<
typename Impl::template proxy<T>::type,
Property
>
{
ASIO_STATIC_CONSTEXPR(overload_type, overload = call_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,
Expand All @@ -191,7 +198,10 @@ struct call_traits<T, void(Property),
!static_require_concept<T, Property>::is_valid
>::type,
typename enable_if<
!require_concept_member<T, Property>::is_valid
!require_concept_member<
typename Impl::template proxy<T>::type,
Property
>::is_valid
>::type,
typename enable_if<
require_concept_free<T, Property>::is_valid
Expand All @@ -203,45 +213,69 @@ struct call_traits<T, void(Property),

struct impl
{
template <typename T>
struct proxy
{
#if defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)
struct type
{
template <typename P>
auto require_concept(ASIO_MOVE_ARG(P) p)
noexcept(
noexcept(
declval<typename conditional<true, T, P>::type>().require_concept(
ASIO_MOVE_CAST(P)(p))
)
)
-> decltype(
declval<typename conditional<true, T, P>::type>().require_concept(
ASIO_MOVE_CAST(P)(p))
);
};
#else // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)
typedef T type;
#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_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_member,
typename call_traits<T, void(Property)>::result_type
call_traits<impl, T, void(Property)>::overload == call_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_concept(
ASIO_MOVE_CAST(Property)(p));
}

template <typename T, typename Property>
ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
call_traits<T, void(Property)>::overload == call_free,
typename call_traits<T, void(Property)>::result_type
call_traits<impl, T, void(Property)>::overload == call_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_concept(
ASIO_MOVE_CAST(T)(t),
Expand All @@ -267,11 +301,14 @@ static ASIO_CONSTEXPR const asio_require_concept_fn::impl&

} // namespace

typedef asio_require_concept_fn::impl require_concept_t;

template <typename T, typename Property>
struct can_require_concept :
integral_constant<bool,
asio_require_concept_fn::call_traits<T, void(Property)>::overload !=
asio_require_concept_fn::ill_formed>
asio_require_concept_fn::call_traits<
require_concept_t, T, void(Property)>::overload !=
asio_require_concept_fn::ill_formed>
{
};

Expand All @@ -286,7 +323,8 @@ constexpr bool can_require_concept_v
template <typename T, typename Property>
struct is_nothrow_require_concept :
integral_constant<bool,
asio_require_concept_fn::call_traits<T, void(Property)>::is_noexcept>
asio_require_concept_fn::call_traits<
require_concept_t, T, void(Property)>::is_noexcept>
{
};

Expand All @@ -302,7 +340,7 @@ template <typename T, typename Property>
struct require_concept_result
{
typedef typename asio_require_concept_fn::call_traits<
T, void(Property)>::result_type type;
require_concept_t, T, void(Property)>::result_type type;
};

} // namespace asio
Expand Down

0 comments on commit 962a85f

Please sign in to comment.