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

161 lines
5.1 KiB
C++

/*
* Copyright (c) Rishabh Dwivedi <rishabhdwivedi17@gmail.com>
*
* 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/async_trace.hpp>
#include <unifex/bind_back.hpp>
#include <unifex/receiver_concepts.hpp>
#include <unifex/sender_concepts.hpp>
#include <unifex/type_list.hpp>
#include <tuple>
#include <variant>
#include <unifex/detail/prologue.hpp>
namespace unifex {
namespace _into_variant {
template <typename Receiver, typename VariantType>
struct _receiver {
struct type;
};
template <typename Receiver, typename VariantType>
using receiver_t = typename _receiver<Receiver, VariantType>::type;
template <typename Receiver, typename VariantType>
struct _receiver<Receiver, VariantType>::type {
UNIFEX_NO_UNIQUE_ADDRESS Receiver receiver_;
template(typename... Values)
(requires receiver_of<Receiver, Values...>)
void set_value(Values&&... values) && {
unifex::set_value((Receiver &&) receiver_,
VariantType(std::make_tuple((Values &&)(values)...)));
}
template(typename Error)
(requires receiver<Receiver, Error>)
void set_error(Error&& error) && noexcept {
unifex::set_error((Receiver &&)(receiver_), (Error &&)(error));
}
void set_done() && noexcept {
unifex::set_done((Receiver &&) receiver_);
}
template(typename CPO)
(requires is_receiver_query_cpo_v<CPO> AND is_callable_v<CPO, const Receiver&>)
friend auto tag_invoke(CPO cpo, const type& r) noexcept(
is_nothrow_callable_v<CPO, const Receiver&>)
-> callable_result_t<CPO, const Receiver&> {
return std::move(cpo)(std::as_const(r.receiver_));
}
template <typename Visit>
friend void tag_invoke(tag_t<visit_continuations>, const type& self, Visit&& visit) {
std::invoke(visit, self.receiver_);
}
};
template <typename Predecessor>
struct _sender {
struct type;
};
template <typename Predecessor>
using sender = typename _sender<remove_cvref_t<Predecessor>>::type;
template <typename Predecessor>
struct _sender<Predecessor>::type {
UNIFEX_NO_UNIQUE_ADDRESS Predecessor pred_;
template <
template <typename...> class Variant,
template <typename...> class Tuple>
using value_types = Variant<Tuple<
sender_value_types_t<Predecessor, std::variant, std::tuple>>>;
template <template <typename...> class Variant>
using error_types = sender_error_types_t<Predecessor, Variant>;
static constexpr bool sends_done = sender_traits<Predecessor>::sends_done;
template <typename Receiver>
using receiver_t = receiver_t<Receiver, sender_value_types_t<Predecessor, std::variant, std::tuple>>;
friend constexpr auto tag_invoke(tag_t<blocking>, const type& sender) {
return blocking(sender.pred_);
}
template(typename Sender, typename Receiver)
(requires same_as<remove_cvref_t<Sender>, type> AND receiver<Receiver> AND
sender_to<member_t<Sender, Predecessor>, receiver_t<remove_cvref_t< Receiver>>>)
friend auto tag_invoke(tag_t<unifex::connect>, Sender&& s, Receiver&& r)
noexcept(
std::is_nothrow_constructible_v<remove_cvref_t<Receiver>, Receiver> &&
is_nothrow_connectable_v<member_t< Sender, Predecessor>, receiver_t<remove_cvref_t<Receiver>>>)
-> connect_result_t<member_t<Sender, Predecessor>, receiver_t<remove_cvref_t<Receiver>>> {
return unifex::connect(
static_cast<Sender&&>(s).pred_,
receiver_t<remove_cvref_t<Receiver>>{
static_cast<Receiver&&>(r)});
}
};
namespace _cpo {
struct _fn {
private:
template <typename Sender>
using _result_t =
typename conditional_t<
tag_invocable<_fn, Sender>,
meta_tag_invoke_result<_fn>,
meta_quote1<_into_variant::sender>>::template apply<Sender>;
public:
template(typename Sender)
(requires tag_invocable<_fn, Sender>)
auto operator()(Sender&& predecessor) const
noexcept(is_nothrow_tag_invocable_v<_fn, Sender>)
-> _result_t<Sender> {
return unifex::tag_invoke(_fn{}, (Sender &&)(predecessor));
}
template(typename Sender)
(requires(!tag_invocable<_fn, Sender>))
auto operator()(Sender&& predecessor) const
noexcept(std::is_nothrow_constructible_v<
_into_variant::sender<Sender>, Sender>)
-> _result_t<Sender> {
return _into_variant::sender<Sender>{(Sender &&) predecessor};
}
constexpr auto operator()() const
noexcept(is_nothrow_callable_v<
tag_t<bind_back>, _fn>)
-> bind_back_result_t<_fn> {
return bind_back(*this);
}
};
} // namespace _cpo
} // namespace _into_variant
inline constexpr _into_variant::_cpo::_fn into_variant{};
} // namespace unifex
#include <unifex/detail/epilogue.hpp>