1 // Copyright (C) 2019 T. Zachary Laine
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
9 #include <boost/stl_interfaces/fwd.hpp>
12 namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V1 {
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).
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`. */
26 element_layout Contiguity = element_layout::discontiguous
27 #ifndef BOOST_STL_INTERFACES_DOXYGEN
29 typename E = std::enable_if_t<
30 std::is_class<Derived>::value &&
31 std::is_same<Derived, std::remove_cv_t<Derived>>::value>
34 struct view_interface;
37 template<typename D, element_layout Contiguity>
38 void derived_view(view_interface<D, Contiguity> const &);
43 element_layout Contiguity
44 #ifndef BOOST_STL_INTERFACES_DOXYGEN
51 #ifndef BOOST_STL_INTERFACES_DOXYGEN
53 constexpr Derived & derived() noexcept
55 return static_cast<Derived &>(*this);
57 constexpr const Derived & derived() const noexcept
59 return static_cast<Derived const &>(*this);
64 template<typename D = Derived>
65 constexpr auto empty() noexcept(
66 noexcept(std::declval<D &>().begin() == std::declval<D &>().end()))
68 std::declval<D &>().begin() == std::declval<D &>().end())
70 return derived().begin() == derived().end();
72 template<typename D = Derived>
73 constexpr auto empty() const noexcept(noexcept(
74 std::declval<D const &>().begin() ==
75 std::declval<D const &>().end()))
77 std::declval<D const &>().begin() ==
78 std::declval<D const &>().end())
80 return derived().begin() == derived().end();
85 typename R = decltype(std::declval<D &>().empty())>
87 operator bool() noexcept(noexcept(std::declval<D &>().empty()))
89 return !derived().empty();
93 typename R = decltype(std::declval<D const &>().empty())>
94 constexpr explicit operator bool() const
95 noexcept(noexcept(std::declval<D const &>().empty()))
97 return !derived().empty();
101 typename D = Derived,
102 element_layout C = Contiguity,
103 typename Enable = std::enable_if_t<C == element_layout::contiguous>>
104 constexpr auto data() noexcept(noexcept(std::declval<D &>().begin()))
105 -> decltype(std::addressof(*std::declval<D &>().begin()))
107 return std::addressof(*derived().begin());
110 typename D = Derived,
111 element_layout C = Contiguity,
112 typename Enable = std::enable_if_t<C == element_layout::contiguous>>
113 constexpr auto data() const
114 noexcept(noexcept(std::declval<D const &>().begin()))
115 -> decltype(std::addressof(*std::declval<D const &>().begin()))
117 return std::addressof(*derived().begin());
120 template<typename D = Derived>
121 constexpr auto size() noexcept(
122 noexcept(std::declval<D &>().end() - std::declval<D &>().begin()))
123 -> decltype(std::declval<D &>().end() - std::declval<D &>().begin())
125 return derived().end() - derived().begin();
127 template<typename D = Derived>
128 constexpr auto size() const noexcept(noexcept(
129 std::declval<D const &>().end() -
130 std::declval<D const &>().begin()))
132 std::declval<D const &>().end() -
133 std::declval<D const &>().begin())
135 return derived().end() - derived().begin();
138 template<typename D = Derived>
139 constexpr auto front() noexcept(noexcept(*std::declval<D &>().begin()))
140 -> decltype(*std::declval<D &>().begin())
142 return *derived().begin();
144 template<typename D = Derived>
145 constexpr auto front() const
146 noexcept(noexcept(*std::declval<D const &>().begin()))
147 -> decltype(*std::declval<D const &>().begin())
149 return *derived().begin();
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>>
158 back() noexcept(noexcept(*std::prev(std::declval<D &>().end())))
159 -> decltype(*std::prev(std::declval<D &>().end()))
161 return *std::prev(derived().end());
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>>
168 constexpr auto back() const
169 noexcept(noexcept(*std::prev(std::declval<D const &>().end())))
170 -> decltype(*std::prev(std::declval<D const &>().end()))
172 return *std::prev(derived().end());
175 template<typename D = Derived>
176 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])
180 return derived().begin()[n];
182 template<typename D = Derived>
183 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])
187 return derived().begin()[n];
191 /** Implementation of `operator!=()` for all views derived from
193 template<typename ViewInterface>
194 constexpr auto operator!=(ViewInterface lhs, ViewInterface rhs) noexcept(
195 noexcept(lhs == rhs))
196 -> decltype(v1_dtl::derived_view(lhs), !(lhs == rhs))
198 return !(lhs == rhs);
204 #if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
206 namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 {
208 /** A template alias for `std::ranges::view_interface`. This only exists
209 to make migration from Boost.STLInterfaces to C++20 easier; switch to
210 the one in `std` as soon as you can. */
211 template<typename D, element_layout = element_layout::discontiguous>
212 using view_interface = std::ranges::view_interface<D>;