123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- // Copyright (C) 2022 T. Zachary Laine
- //
- // Distributed under the Boost Software License, Version 1.0. (See
- // accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_STL_INTERFACES_DETAIL_PIPEABLE_VIEW_HPP
- #define BOOST_STL_INTERFACES_DETAIL_PIPEABLE_VIEW_HPP
- #include <boost/stl_interfaces/config.hpp>
- #include <type_traits>
- namespace boost { namespace stl_interfaces { namespace detail {
- template<typename T>
- using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
- struct pipeable_base;
- #if BOOST_STL_INTERFACES_USE_CONCEPTS
- template<typename T>
- concept pipeable_ = std::derived_from<T, pipeable_base> &&
- std::is_object_v<T> && std::copy_constructible<T>;
- #else
- template<typename T>
- constexpr bool pipeable_ = std::is_base_of<pipeable_base, T>::value &&
- std::is_object<T>::value && std::is_copy_constructible<T>::value;
- #endif
- #if BOOST_STL_INTERFACES_USE_CONCEPTS
- template<pipeable_ T, pipeable_ U>
- #else
- template<
- typename T,
- typename U,
- typename Enable = std::enable_if_t<pipeable_<T> && pipeable_<U>>>
- #endif
- struct view_pipeline;
- struct pipeable_base
- {
- #if BOOST_STL_INTERFACES_USE_CONCEPTS
- template<pipeable_ T, pipeable_ U>
- requires std::constructible_from<std::remove_cvref_t<T>, T> &&
- std::constructible_from<std::remove_cvref_t<U>, U>
- #else
- template<
- typename T,
- typename U,
- typename Enable = std::enable_if_t<
- pipeable_<T> && pipeable_<U> &&
- std::is_constructible<remove_cvref_t<T>, T>::value &&
- std::is_constructible<remove_cvref_t<U>, U>::value>>
- #endif
- friend constexpr auto operator|(T && t, U && u)
- {
- return view_pipeline<T, U>{(T &&) t, (U &&) u};
- }
- };
- template<typename Derived>
- struct pipeable : pipeable_base
- {
- template<typename R>
- friend constexpr auto operator|(R && r, Derived & d)
- -> decltype(((Derived &&) d)((R &&) r))
- {
- return ((Derived &&) d)((R &&) r);
- }
- template<typename R>
- friend constexpr auto operator|(R && r, Derived const & d)
- -> decltype(((Derived &&) d)((R &&) r))
- {
- return ((Derived &&) d)((R &&) r);
- }
- template<typename R>
- friend constexpr auto operator|(R && r, Derived && d)
- -> decltype(((Derived &&) d)((R &&) r))
- {
- return ((Derived &&) d)((R &&) r);
- }
- };
- #if BOOST_STL_INTERFACES_USE_CONCEPTS
- template<pipeable_ T, pipeable_ U>
- #else
- template<typename T, typename U, typename>
- #endif
- struct view_pipeline : pipeable<view_pipeline<T, U>>
- {
- view_pipeline() = default;
- constexpr view_pipeline(T && t, U && u) :
- left_(std::move(t)), right_(std::move(u))
- {}
- #if BOOST_STL_INTERFACES_USE_CONCEPTS
- template<std::ranges::viewable_range R>
- requires std::invocable<T &, R> &&
- std::invocable<U &, std::invoke_result_t<T &, R>>
- constexpr decltype(auto) operator()(R && r) &
- #else
- template<typename R>
- constexpr auto
- operator()(R && r) & -> decltype(this->right_(this->left_((R &&) r)))
- #endif
- {
- return right_(left_((R &&) r));
- }
- #if BOOST_STL_INTERFACES_USE_CONCEPTS
- template<std::ranges::viewable_range R>
- requires std::invocable<T const &, R> &&
- std::invocable<U const &, std::invoke_result_t<T const &, R>>
- constexpr decltype(auto) operator()(R && r) const &
- #else
- template<typename R>
- constexpr auto operator()(
- R && r) const & -> decltype(this->right_(this->left_((R &&) r)))
- #endif
- {
- return right_(left_((R &&) r));
- }
- #if BOOST_STL_INTERFACES_USE_CONCEPTS
- template<std::ranges::viewable_range R>
- requires std::invocable<T, R> &&
- std::invocable<U, std::invoke_result_t<T, R>>
- constexpr decltype(auto) operator()(R && r) &&
- #else
- template<typename R>
- constexpr auto operator()(R && r) && -> decltype(std::move(
- this->right_)(std::move(this->left_)((R &&) r)))
- #endif
- {
- return std::move(right_)(std::move(left_)((R &&) r));
- }
- T left_;
- U right_;
- };
- }}}
- #endif
|