AimRT/install_x64/include/unifex/receiver_concepts.hpp
2025-01-12 19:51:34 +08:00

265 lines
9.1 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License Version 2.0 with LLVM Exceptions
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://llvm.org/LICENSE.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <unifex/config.hpp>
#include <unifex/tag_invoke.hpp>
#include <unifex/type_traits.hpp>
#include <unifex/std_concepts.hpp>
#include <unifex/detail/unifex_fwd.hpp>
#include <exception>
#include <type_traits>
#include <unifex/detail/prologue.hpp>
namespace unifex {
namespace _rec_cpo {
inline const struct _set_value_fn {
private:
template <typename Receiver, typename... Values>
using set_value_member_result_t =
decltype(UNIFEX_DECLVAL(Receiver).set_value(UNIFEX_DECLVAL(Values)...));
template <typename Receiver, typename... Values>
using _result_t =
typename conditional_t<
tag_invocable<_set_value_fn, Receiver, Values...>,
meta_tag_invoke_result<_set_value_fn>,
meta_quote1_<set_value_member_result_t>>::template apply<Receiver, Values...>;
public:
template(typename Receiver, typename... Values)
(requires tag_invocable<_set_value_fn, Receiver, Values...>)
auto operator()(Receiver&& r, Values&&... values) const
noexcept(
is_nothrow_tag_invocable_v<_set_value_fn, Receiver, Values...>)
-> _result_t<Receiver, Values...> {
return unifex::tag_invoke(
_set_value_fn{}, (Receiver &&) r, (Values &&) values...);
}
template(typename Receiver, typename... Values)
(requires (!tag_invocable<_set_value_fn, Receiver, Values...>))
auto operator()(Receiver&& r, Values&&... values) const
noexcept(noexcept(
static_cast<Receiver&&>(r).set_value((Values &&) values...)))
-> _result_t<Receiver, Values...> {
return static_cast<Receiver&&>(r).set_value((Values &&) values...);
}
} set_value{};
inline const struct _set_next_fn {
private:
template <typename Receiver, typename... Values>
using set_next_member_result_t =
decltype(UNIFEX_DECLVAL(Receiver&).set_next(UNIFEX_DECLVAL(Values)...));
template <typename Receiver, typename... Values>
using _result_t =
typename conditional_t<
tag_invocable<_set_next_fn, Receiver&, Values...>,
meta_tag_invoke_result<_set_next_fn>,
meta_quote1_<set_next_member_result_t>>::template apply<Receiver, Values...>;
public:
template(typename Receiver, typename... Values)
(requires tag_invocable<_set_next_fn, Receiver, Values...>)
auto operator()(Receiver& r, Values&&... values) const
noexcept(
is_nothrow_tag_invocable_v<_set_next_fn, Receiver, Values...>)
-> _result_t<Receiver, Values...> {
return unifex::tag_invoke(
_set_next_fn{}, r, (Values &&) values...);
}
template(typename Receiver, typename... Values)
(requires (!tag_invocable<_set_next_fn, Receiver&, Values...>))
auto operator()(Receiver& r, Values&&... values) const
noexcept(noexcept(
r.set_next((Values &&) values...)))
-> _result_t<Receiver, Values...> {
return r.set_next((Values &&) values...);
}
} set_next{};
inline const struct _set_error_fn {
private:
template <typename Receiver, typename Error>
using set_error_member_result_t =
decltype(UNIFEX_DECLVAL(Receiver).set_error(UNIFEX_DECLVAL(Error)));
template <typename Receiver, typename Error>
using _result_t =
typename conditional_t<
tag_invocable<_set_error_fn, Receiver, Error>,
meta_tag_invoke_result<_set_error_fn>,
meta_quote2<set_error_member_result_t>>::template apply<Receiver, Error>;
public:
template(typename Receiver, typename Error)
(requires tag_invocable<_set_error_fn, Receiver, Error>)
auto operator()(Receiver&& r, Error&& error) const noexcept
-> _result_t<Receiver, Error> {
static_assert(
is_nothrow_tag_invocable_v<_set_error_fn, Receiver, Error>,
"set_error() invocation is required to be noexcept.");
static_assert(
std::is_void_v<tag_invoke_result_t<_set_error_fn, Receiver, Error>>
);
return unifex::tag_invoke(
_set_error_fn{}, (Receiver &&) r, (Error&&) error);
}
template(typename Receiver, typename Error)
(requires (!tag_invocable<_set_error_fn, Receiver, Error>))
auto operator()(Receiver&& r, Error&& error) const noexcept
-> _result_t<Receiver, Error> {
static_assert(
noexcept(static_cast<Receiver&&>(r).set_error((Error &&) error)),
"receiver.set_error() method must be nothrow invocable");
return static_cast<Receiver&&>(r).set_error((Error&&) error);
}
} set_error{};
inline const struct _set_done_fn {
private:
template <typename Receiver>
using set_done_member_result_t =
decltype(UNIFEX_DECLVAL(Receiver).set_done());
template <typename Receiver>
using _result_t =
typename conditional_t<
tag_invocable<_set_done_fn, Receiver>,
meta_tag_invoke_result<_set_done_fn>,
meta_quote1<set_done_member_result_t>>::template apply<Receiver>;
public:
template(typename Receiver)
(requires tag_invocable<_set_done_fn, Receiver>)
auto operator()(Receiver&& r) const noexcept
-> _result_t<Receiver> {
static_assert(
is_nothrow_tag_invocable_v<_set_done_fn, Receiver>,
"set_done() invocation is required to be noexcept.");
static_assert(
std::is_void_v<tag_invoke_result_t<_set_done_fn, Receiver>>
);
return unifex::tag_invoke(_set_done_fn{}, (Receiver &&) r);
}
template(typename Receiver)
(requires (!tag_invocable<_set_done_fn, Receiver>))
auto operator()(Receiver&& r) const noexcept
-> _result_t<Receiver> {
static_assert(
noexcept(static_cast<Receiver&&>(r).set_done()),
"receiver.set_done() method must be nothrow invocable");
return static_cast<Receiver&&>(r).set_done();
}
} set_done{};
} // namespace _rec_cpo
using _rec_cpo::set_value;
using _rec_cpo::set_next;
using _rec_cpo::set_error;
using _rec_cpo::set_done;
template <typename T>
inline constexpr bool is_receiver_cpo_v = is_one_of_v<
remove_cvref_t<T>,
_rec_cpo::_set_value_fn,
_rec_cpo::_set_next_fn,
_rec_cpo::_set_error_fn,
_rec_cpo::_set_done_fn>;
// HACK: Approximation for CPOs that should be forwarded through receivers
// as query operations.
template <typename T>
inline constexpr bool is_receiver_query_cpo_v = !is_one_of_v<
remove_cvref_t<T>,
_rec_cpo::_set_value_fn,
_rec_cpo::_set_next_fn,
_rec_cpo::_set_error_fn,
_rec_cpo::_set_done_fn,
_connect::_cpo::_fn>;
template <typename T>
using is_receiver_cpo = std::bool_constant<is_receiver_cpo_v<T>>;
#if UNIFEX_CXX_CONCEPTS
// Defined the receiver concepts without the macros for improved diagnostics
template <typename R, typename E = std::exception_ptr>
concept //
receiver = //
move_constructible<remove_cvref_t<R>> &&
constructible_from<remove_cvref_t<R>, R> &&
requires(remove_cvref_t<R>&& r, E&& e)
{
{ set_done(std::move(r)) } noexcept;
{ set_error(std::move(r), (E&&) e) } noexcept;
};
template <typename R, typename... An>
concept //
receiver_of = //
receiver<R> &&
requires(remove_cvref_t<R>&& r, An&&... an) //
{
set_value(std::move(r), (An&&) an...);
};
#else
template <typename R, typename E>
UNIFEX_CONCEPT_FRAGMENT(
_receiver,
requires(remove_cvref_t<R>&& r, E&& e) //
(
noexcept(set_done(std::move(r))),
noexcept(set_error(std::move(r), (E&&) e))
));
template <typename R, typename E = std::exception_ptr>
UNIFEX_CONCEPT //
receiver = //
move_constructible<remove_cvref_t<R>> &&
constructible_from<remove_cvref_t<R>, R> &&
UNIFEX_FRAGMENT(unifex::_receiver, R, E);
template <typename T, typename... An>
UNIFEX_CONCEPT_FRAGMENT( //
_receiver_of, //
requires(remove_cvref_t<T>&& t, An&&... an) //
(
set_value(std::move(t), (An&&) an...)
));
template <typename R, typename... An>
UNIFEX_CONCEPT //
receiver_of = //
receiver<R> &&
UNIFEX_FRAGMENT(unifex::_receiver_of, R, An...);
#endif
template <typename R, typename... An>
inline constexpr bool is_nothrow_receiver_of_v =
receiver_of<R, An...> &&
is_nothrow_callable_v<tag_t<set_value>, R, An...>;
//////////////////
// Metafunctions for checking callability of specific receiver methods
template <typename R, typename... An>
inline constexpr bool is_next_receiver_v =
is_callable_v<decltype(set_next), R&, An...>;
template <typename R, typename... An>
inline constexpr bool is_nothrow_next_receiver_v =
is_nothrow_callable_v<decltype(set_next), R&, An...>;
} // namespace unifex
#include <unifex/detail/epilogue.hpp>