1// Copyright (C) 2022 T. Zachary Laine
2//
3// Distributed under the Boost Software License, Version 1.0. (See
4// accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6#ifndef BOOST_STL_INTERFACES_DETAIL_PIPEABLE_VIEW_HPP
7#define BOOST_STL_INTERFACES_DETAIL_PIPEABLE_VIEW_HPP
8
9#include <boost/stl_interfaces/config.hpp>
10
11#include <type_traits>
12
13
14namespace boost { namespace stl_interfaces { namespace detail {
15
16 template<typename T>
17 using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
18
19 struct pipeable_base;
20
21#if BOOST_STL_INTERFACES_USE_CONCEPTS
22 template<typename T>
23 concept pipeable_ = std::derived_from<T, pipeable_base> &&
24 std::is_object_v<T> && std::copy_constructible<T>;
25#else
26 template<typename T>
27 constexpr bool pipeable_ = std::is_base_of<pipeable_base, T>::value &&
28 std::is_object<T>::value && std::is_copy_constructible<T>::value;
29#endif
30
31#if BOOST_STL_INTERFACES_USE_CONCEPTS
32 template<pipeable_ T, pipeable_ U>
33#else
34 template<
35 typename T,
36 typename U,
37 typename Enable = std::enable_if_t<pipeable_<T> && pipeable_<U>>>
38#endif
39 struct view_pipeline;
40
41 struct pipeable_base
42 {
43#if BOOST_STL_INTERFACES_USE_CONCEPTS
44 template<pipeable_ T, pipeable_ U>
45 requires std::constructible_from<std::remove_cvref_t<T>, T> &&
46 std::constructible_from<std::remove_cvref_t<U>, U>
47#else
48 template<
49 typename T,
50 typename U,
51 typename Enable = std::enable_if_t<
52 pipeable_<T> && pipeable_<U> &&
53 std::is_constructible<remove_cvref_t<T>, T>::value &&
54 std::is_constructible<remove_cvref_t<U>, U>::value>>
55#endif
56 friend constexpr auto operator|(T && t, U && u)
57 {
58 return view_pipeline<T, U>{(T &&) t, (U &&) u};
59 }
60 };
61
62 template<typename Derived>
63 struct pipeable : pipeable_base
64 {
65 template<typename R>
66 friend constexpr auto operator|(R && r, Derived & d)
67 -> decltype(((Derived &&) d)((R &&) r))
68 {
69 return ((Derived &&) d)((R &&) r);
70 }
71
72 template<typename R>
73 friend constexpr auto operator|(R && r, Derived const & d)
74 -> decltype(((Derived &&) d)((R &&) r))
75 {
76 return ((Derived &&) d)((R &&) r);
77 }
78
79 template<typename R>
80 friend constexpr auto operator|(R && r, Derived && d)
81 -> decltype(((Derived &&) d)((R &&) r))
82 {
83 return ((Derived &&) d)((R &&) r);
84 }
85 };
86
87#if BOOST_STL_INTERFACES_USE_CONCEPTS
88 template<pipeable_ T, pipeable_ U>
89#else
90 template<typename T, typename U, typename>
91#endif
92 struct view_pipeline : pipeable<view_pipeline<T, U>>
93 {
94 view_pipeline() = default;
95
96 constexpr view_pipeline(T && t, U && u) :
97 left_(std::move(t)), right_(std::move(u))
98 {}
99
100#if BOOST_STL_INTERFACES_USE_CONCEPTS
101 template<std::ranges::viewable_range R>
102 requires std::invocable<T &, R> &&
103 std::invocable<U &, std::invoke_result_t<T &, R>>
104 constexpr decltype(auto) operator()(R && r) &
105#else
106 template<typename R>
107 constexpr auto
108 operator()(R && r) & -> decltype(this->right_(this->left_((R &&) r)))
109#endif
110 {
111 return right_(left_((R &&) r));
112 }
113
114#if BOOST_STL_INTERFACES_USE_CONCEPTS
115 template<std::ranges::viewable_range R>
116 requires std::invocable<T const &, R> &&
117 std::invocable<U const &, std::invoke_result_t<T const &, R>>
118 constexpr decltype(auto) operator()(R && r) const &
119#else
120 template<typename R>
121 constexpr auto operator()(
122 R && r) const & -> decltype(this->right_(this->left_((R &&) r)))
123#endif
124 {
125 return right_(left_((R &&) r));
126 }
127
128#if BOOST_STL_INTERFACES_USE_CONCEPTS
129 template<std::ranges::viewable_range R>
130 requires std::invocable<T, R> &&
131 std::invocable<U, std::invoke_result_t<T, R>>
132 constexpr decltype(auto) operator()(R && r) &&
133#else
134 template<typename R>
135 constexpr auto operator()(R && r) && -> decltype(std::move(
136 this->right_)(std::move(this->left_)((R &&) r)))
137#endif
138 {
139 return std::move(right_)(std::move(left_)((R &&) r));
140 }
141
142 T left_;
143 U right_;
144 };
145
146}}}
147
148#endif
149

source code of boost/libs/stl_interfaces/include/boost/stl_interfaces/detail/pipeable_view.hpp