/* * 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 #include #include #include #include #include namespace unifex { namespace _compose { struct _fn { template auto operator()(Target&& target, Other&& other, Self&& self) const noexcept( is_nothrow_callable_v && is_nothrow_callable_v>) -> callable_result_t> { return ((Self&&) self)(((Other&&) other)((Target&&) target)); } }; } // namespace _compose namespace _bind_back { template struct _apply_fn_impl { struct type; }; template using _apply_fn = typename _apply_fn_impl::type; template struct _apply_fn_impl::type { Cpo&& cpo_; Target&& target_; template (typename... ArgN) (requires callable) auto operator()(ArgN&&... argN) noexcept(is_nothrow_callable_v) -> callable_result_t { return ((Cpo&&) cpo_)((Target&&) target_, (ArgN&&) argN...); } }; struct _result_base {}; template struct _result_impl { struct type; }; template using _result = typename _result_impl::type; template struct _result_impl::type : _result_base { UNIFEX_NO_UNIQUE_ADDRESS Cpo cpo_; std::tuple argN_; template (typename Target) (requires (!derived_from, _result_base>) AND callable) decltype(auto) operator()(Target&& target) const & noexcept(is_nothrow_callable_v) { return std::apply(_apply_fn{cpo_, (Target&&) target}, argN_); } template (typename Target) (requires (!derived_from, _result_base>) AND callable) decltype(auto) operator()(Target&& target) && noexcept(is_nothrow_callable_v) { return std::apply( _apply_fn{(Cpo&&) cpo_, (Target&&) target}, std::move(argN_)); } template (typename Target, typename Self) (requires (!derived_from, _result_base>) AND same_as, type> AND callable, Target, member_t...>) friend decltype(auto) operator|(Target&& target, Self&& self) noexcept( is_nothrow_callable_v, Target, member_t...>) { return std::apply( _apply_fn, Target>{((Self&&) self).cpo_, (Target&&) target}, ((Self&&) self).argN_); } template (typename Other, typename Self) (requires derived_from, _result_base> AND same_as, type>) friend decltype(auto) operator|(Other&& other, Self&& self) noexcept(noexcept( _result<_compose::_fn, remove_cvref_t, type>{ {}, // _result_base {}, // _compose::_fn {(Other&&) other, (Self&&) self}})) { return _result<_compose::_fn, remove_cvref_t, type>{ {}, // _result_base {}, // _compose::_fn {(Other&&) other, (Self&&) self}}; } }; inline const struct _fn { template constexpr auto operator()(Cpo cpo, ArgN&&... argN) const noexcept(noexcept( _result...>{{}, (Cpo&&) cpo, {(ArgN &&) argN...}})) -> _result...> { return _result...>{{}, (Cpo&&) cpo, {(ArgN &&) argN...}}; } } bind_back{}; } // namespace _bind_back using _bind_back::bind_back; template using bind_back_result_t = _bind_back::_result, std::decay_t...>; } // namespace unifex #include