• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2019 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_VIEW_INTERFACE_HPP
7 #define BOOST_STL_INTERFACES_VIEW_INTERFACE_HPP
8 
9 #include <boost/stl_interfaces/fwd.hpp>
10 
11 
12 namespace boost { namespace stl_interfaces { inline namespace v1 {
13 
14     /** A CRTP template that one may derive from to make it easier to define
15         `std::ranges::view`-like types with a container-like interface.  This
16         is a pre-C++20 version of C++20's `view_interface` (see
17         [view.interface] in the C++ standard).
18 
19         The template parameter `D` for `view_interface` may be an incomplete
20         type.  Before any member of the resulting specialization of
21         `view_interface` other than special member functions is referenced,
22         `D` shall be complete, and model both
23         `std::derived_from<view_interface<D>>` and `std::view`. */
24     template<
25         typename Derived,
26         element_layout Contiguity = element_layout::discontiguous
27 #ifndef BOOST_STL_INTERFACES_DOXYGEN
28         ,
29         typename E = std::enable_if_t<
30             std::is_class<Derived>::value &&
31             std::is_same<Derived, std::remove_cv_t<Derived>>::value>
32 #endif
33         >
34     struct view_interface;
35 
36     namespace v1_dtl {
37         template<typename D, element_layout Contiguity>
38         void derived_view(view_interface<D, Contiguity> const &);
39     }
40 
41     template<
42         typename Derived,
43         element_layout Contiguity
44 #ifndef BOOST_STL_INTERFACES_DOXYGEN
45         ,
46         typename E
47 #endif
48         >
49     struct view_interface
50     {
51 #ifndef BOOST_STL_INTERFACES_DOXYGEN
52     private:
derivedboost::stl_interfaces::v1::view_interface53         constexpr Derived & derived() noexcept
54         {
55             return static_cast<Derived &>(*this);
56         }
derivedboost::stl_interfaces::v1::view_interface57         constexpr const Derived & derived() const noexcept
58         {
59             return static_cast<Derived const &>(*this);
60         }
61 #endif
62 
63     public:
64         template<typename D = Derived>
emptyboost::stl_interfaces::v1::view_interface65         constexpr auto empty() noexcept(
66             noexcept(std::declval<D &>().begin() == std::declval<D &>().end()))
67             -> decltype(
68                 std::declval<D &>().begin() == std::declval<D &>().end())
69         {
70             return derived().begin() == derived().end();
71         }
72         template<typename D = Derived>
emptyboost::stl_interfaces::v1::view_interface73         constexpr auto empty() const noexcept(noexcept(
74             std::declval<D const &>().begin() ==
75             std::declval<D const &>().end()))
76             -> decltype(
77                 std::declval<D const &>().begin() ==
78                 std::declval<D const &>().end())
79         {
80             return derived().begin() == derived().end();
81         }
82 
83         template<
84             typename D = Derived,
85             typename R = decltype(std::declval<D &>().empty())>
86         constexpr explicit
operator boolboost::stl_interfaces::v1::view_interface87         operator bool() noexcept(noexcept(std::declval<D &>().empty()))
88         {
89             return !derived().empty();
90         }
91         template<
92             typename D = Derived,
93             typename R = decltype(std::declval<D const &>().empty())>
operator boolboost::stl_interfaces::v1::view_interface94         constexpr explicit operator bool() const
95             noexcept(noexcept(std::declval<D const &>().empty()))
96         {
97             return !derived().empty();
98         }
99 
100         template<
101             typename D = Derived,
102             element_layout C = Contiguity,
103             typename Enable = std::enable_if_t<C == element_layout::contiguous>>
databoost::stl_interfaces::v1::view_interface104         constexpr auto data() noexcept(noexcept(std::declval<D &>().begin()))
105             -> decltype(std::addressof(*std::declval<D &>().begin()))
106         {
107             return std::addressof(*derived().begin());
108         }
109         template<
110             typename D = Derived,
111             element_layout C = Contiguity,
112             typename Enable = std::enable_if_t<C == element_layout::contiguous>>
databoost::stl_interfaces::v1::view_interface113         constexpr auto data() const
114             noexcept(noexcept(std::declval<D const &>().begin()))
115                 -> decltype(std::addressof(*std::declval<D const &>().begin()))
116         {
117             return std::addressof(*derived().begin());
118         }
119 
120         template<typename D = Derived>
sizeboost::stl_interfaces::v1::view_interface121         constexpr auto size() noexcept(
122             noexcept(std::declval<D &>().end() - std::declval<D &>().begin()))
123             -> decltype(std::declval<D &>().end() - std::declval<D &>().begin())
124         {
125             return derived().end() - derived().begin();
126         }
127         template<typename D = Derived>
sizeboost::stl_interfaces::v1::view_interface128         constexpr auto size() const noexcept(noexcept(
129             std::declval<D const &>().end() -
130             std::declval<D const &>().begin()))
131             -> decltype(
132                 std::declval<D const &>().end() -
133                 std::declval<D const &>().begin())
134         {
135             return derived().end() - derived().begin();
136         }
137 
138         template<typename D = Derived>
frontboost::stl_interfaces::v1::view_interface139         constexpr auto front() noexcept(noexcept(*std::declval<D &>().begin()))
140             -> decltype(*std::declval<D &>().begin())
141         {
142             return *derived().begin();
143         }
144         template<typename D = Derived>
frontboost::stl_interfaces::v1::view_interface145         constexpr auto front() const
146             noexcept(noexcept(*std::declval<D const &>().begin()))
147                 -> decltype(*std::declval<D const &>().begin())
148         {
149             return *derived().begin();
150         }
151 
152         template<
153             typename D = Derived,
154             typename Enable = std::enable_if_t<
155                 v1_dtl::decrementable_sentinel<D>::value &&
156                 v1_dtl::common_range<D>::value>>
157         constexpr auto
backboost::stl_interfaces::v1::view_interface158         back() noexcept(noexcept(*std::prev(std::declval<D &>().end())))
159             -> decltype(*std::prev(std::declval<D &>().end()))
160         {
161             return *std::prev(derived().end());
162         }
163         template<
164             typename D = Derived,
165             typename Enable = std::enable_if_t<
166                 v1_dtl::decrementable_sentinel<D>::value &&
167                 v1_dtl::common_range<D>::value>>
backboost::stl_interfaces::v1::view_interface168         constexpr auto back() const
169             noexcept(noexcept(*std::prev(std::declval<D const &>().end())))
170                 -> decltype(*std::prev(std::declval<D const &>().end()))
171         {
172             return *std::prev(derived().end());
173         }
174 
175         template<typename D = Derived>
operator []boost::stl_interfaces::v1::view_interface176         constexpr auto operator[](v1_dtl::range_difference_t<D> n) noexcept(
177             noexcept(std::declval<D &>().begin()[n]))
178             -> decltype(std::declval<D &>().begin()[n])
179         {
180             return derived().begin()[n];
181         }
182         template<typename D = Derived>
operator []boost::stl_interfaces::v1::view_interface183         constexpr auto operator[](v1_dtl::range_difference_t<D> n) const
184             noexcept(noexcept(std::declval<D const &>().begin()[n]))
185                 -> decltype(std::declval<D const &>().begin()[n])
186         {
187             return derived().begin()[n];
188         }
189     };
190 
191     /** Implementation of `operator!=()` for all views derived from
192         `view_interface`. */
193     template<typename ViewInterface>
operator !=(ViewInterface lhs,ViewInterface rhs)194     constexpr auto operator!=(ViewInterface lhs, ViewInterface rhs) noexcept(
195         noexcept(lhs == rhs))
196         -> decltype(v1_dtl::derived_view(lhs), !(lhs == rhs))
197     {
198         return !(lhs == rhs);
199     }
200 
201 }}}
202 
203 
204 #if 201703L < __cplusplus && defined(__cpp_lib_concepts) ||                    \
205     defined(BOOST_STL_INTERFACES_DOXYGEN)
206 
207 #include <ranges>
208 
209 namespace boost { namespace stl_interfaces { namespace v2 {
210 
211     /** A template alias for `std::view_interface`.  This only exists to make
212         migration from Boost.STLInterfaces to C++20 easier; switch to the one
213         in `std` as soon as you can. */
214     template<typename D, bool = false>
215     using view_interface = std::ranges::view_interface<D>;
216 
217 }}}
218 
219 #endif
220 
221 #endif
222