File indexing completed on 2025-01-18 09:52:33
0001
0002
0003
0004
0005
0006 #ifndef BOOST_STL_INTERFACES_DETAIL_PIPEABLE_VIEW_HPP
0007 #define BOOST_STL_INTERFACES_DETAIL_PIPEABLE_VIEW_HPP
0008
0009 #include <boost/stl_interfaces/config.hpp>
0010
0011 #include <type_traits>
0012
0013
0014 namespace boost { namespace stl_interfaces { namespace detail {
0015
0016 template<typename T>
0017 using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
0018
0019 struct pipeable_base;
0020
0021 #if BOOST_STL_INTERFACES_USE_CONCEPTS
0022 template<typename T>
0023 concept pipeable_ = std::derived_from<T, pipeable_base> &&
0024 std::is_object_v<T> && std::copy_constructible<T>;
0025 #else
0026 template<typename T>
0027 constexpr bool pipeable_ = std::is_base_of<pipeable_base, T>::value &&
0028 std::is_object<T>::value && std::is_copy_constructible<T>::value;
0029 #endif
0030
0031 #if BOOST_STL_INTERFACES_USE_CONCEPTS
0032 template<pipeable_ T, pipeable_ U>
0033 #else
0034 template<
0035 typename T,
0036 typename U,
0037 typename Enable = std::enable_if_t<pipeable_<T> && pipeable_<U>>>
0038 #endif
0039 struct view_pipeline;
0040
0041 struct pipeable_base
0042 {
0043 #if BOOST_STL_INTERFACES_USE_CONCEPTS
0044 template<pipeable_ T, pipeable_ U>
0045 requires std::constructible_from<std::remove_cvref_t<T>, T> &&
0046 std::constructible_from<std::remove_cvref_t<U>, U>
0047 #else
0048 template<
0049 typename T,
0050 typename U,
0051 typename Enable = std::enable_if_t<
0052 pipeable_<T> && pipeable_<U> &&
0053 std::is_constructible<remove_cvref_t<T>, T>::value &&
0054 std::is_constructible<remove_cvref_t<U>, U>::value>>
0055 #endif
0056 friend constexpr auto operator|(T && t, U && u)
0057 {
0058 return view_pipeline<T, U>{(T &&) t, (U &&) u};
0059 }
0060 };
0061
0062 template<typename Derived>
0063 struct pipeable : pipeable_base
0064 {
0065 template<typename R>
0066 friend constexpr auto operator|(R && r, Derived & d)
0067 -> decltype(((Derived &&) d)((R &&) r))
0068 {
0069 return ((Derived &&) d)((R &&) r);
0070 }
0071
0072 template<typename R>
0073 friend constexpr auto operator|(R && r, Derived const & d)
0074 -> decltype(((Derived &&) d)((R &&) r))
0075 {
0076 return ((Derived &&) d)((R &&) r);
0077 }
0078
0079 template<typename R>
0080 friend constexpr auto operator|(R && r, Derived && d)
0081 -> decltype(((Derived &&) d)((R &&) r))
0082 {
0083 return ((Derived &&) d)((R &&) r);
0084 }
0085 };
0086
0087 #if BOOST_STL_INTERFACES_USE_CONCEPTS
0088 template<pipeable_ T, pipeable_ U>
0089 #else
0090 template<typename T, typename U, typename>
0091 #endif
0092 struct view_pipeline : pipeable<view_pipeline<T, U>>
0093 {
0094 view_pipeline() = default;
0095
0096 constexpr view_pipeline(T && t, U && u) :
0097 left_(std::move(t)), right_(std::move(u))
0098 {}
0099
0100 #if BOOST_STL_INTERFACES_USE_CONCEPTS
0101 template<std::ranges::viewable_range R>
0102 requires std::invocable<T &, R> &&
0103 std::invocable<U &, std::invoke_result_t<T &, R>>
0104 constexpr decltype(auto) operator()(R && r) &
0105 #else
0106 template<typename R>
0107 constexpr auto
0108 operator()(R && r) & -> decltype(this->right_(this->left_((R &&) r)))
0109 #endif
0110 {
0111 return right_(left_((R &&) r));
0112 }
0113
0114 #if BOOST_STL_INTERFACES_USE_CONCEPTS
0115 template<std::ranges::viewable_range R>
0116 requires std::invocable<T const &, R> &&
0117 std::invocable<U const &, std::invoke_result_t<T const &, R>>
0118 constexpr decltype(auto) operator()(R && r) const &
0119 #else
0120 template<typename R>
0121 constexpr auto operator()(
0122 R && r) const & -> decltype(this->right_(this->left_((R &&) r)))
0123 #endif
0124 {
0125 return right_(left_((R &&) r));
0126 }
0127
0128 #if BOOST_STL_INTERFACES_USE_CONCEPTS
0129 template<std::ranges::viewable_range R>
0130 requires std::invocable<T, R> &&
0131 std::invocable<U, std::invoke_result_t<T, R>>
0132 constexpr decltype(auto) operator()(R && r) &&
0133 #else
0134 template<typename R>
0135 constexpr auto operator()(R && r) && -> decltype(std::move(
0136 this->right_)(std::move(this->left_)((R &&) r)))
0137 #endif
0138 {
0139 return std::move(right_)(std::move(left_)((R &&) r));
0140 }
0141
0142 T left_;
0143 U right_;
0144 };
0145
0146 }}}
0147
0148 #endif