123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- // Copyright (C) 2019 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_VIEW_INTERFACE_HPP
- #define BOOST_STL_INTERFACES_VIEW_INTERFACE_HPP
- #include <boost/stl_interfaces/fwd.hpp>
- namespace boost { namespace stl_interfaces { inline namespace v1 {
- /** A CRTP template that one may derive from to make it easier to define
- `std::ranges::view`-like types with a container-like interface. This
- is a pre-C++20 version of C++20's `view_interface` (see
- [view.interface] in the C++ standard).
- The template parameter `D` for `view_interface` may be an incomplete
- type. Before any member of the resulting specialization of
- `view_interface` other than special member functions is referenced,
- `D` shall be complete, and model both
- `std::derived_from<view_interface<D>>` and `std::view`. */
- template<
- typename Derived,
- element_layout Contiguity = element_layout::discontiguous
- #ifndef BOOST_STL_INTERFACES_DOXYGEN
- ,
- typename E = std::enable_if_t<
- std::is_class<Derived>::value &&
- std::is_same<Derived, std::remove_cv_t<Derived>>::value>
- #endif
- >
- struct view_interface;
- namespace v1_dtl {
- template<typename D, element_layout Contiguity>
- void derived_view(view_interface<D, Contiguity> const &);
- }
- template<
- typename Derived,
- element_layout Contiguity
- #ifndef BOOST_STL_INTERFACES_DOXYGEN
- ,
- typename E
- #endif
- >
- struct view_interface
- {
- #ifndef BOOST_STL_INTERFACES_DOXYGEN
- private:
- constexpr Derived & derived() noexcept
- {
- return static_cast<Derived &>(*this);
- }
- constexpr const Derived & derived() const noexcept
- {
- return static_cast<Derived const &>(*this);
- }
- #endif
- public:
- template<typename D = Derived>
- constexpr auto empty() noexcept(
- noexcept(std::declval<D &>().begin() == std::declval<D &>().end()))
- -> decltype(
- std::declval<D &>().begin() == std::declval<D &>().end())
- {
- return derived().begin() == derived().end();
- }
- template<typename D = Derived>
- constexpr auto empty() const noexcept(noexcept(
- std::declval<D const &>().begin() ==
- std::declval<D const &>().end()))
- -> decltype(
- std::declval<D const &>().begin() ==
- std::declval<D const &>().end())
- {
- return derived().begin() == derived().end();
- }
- template<
- typename D = Derived,
- typename R = decltype(std::declval<D &>().empty())>
- constexpr explicit
- operator bool() noexcept(noexcept(std::declval<D &>().empty()))
- {
- return !derived().empty();
- }
- template<
- typename D = Derived,
- typename R = decltype(std::declval<D const &>().empty())>
- constexpr explicit operator bool() const
- noexcept(noexcept(std::declval<D const &>().empty()))
- {
- return !derived().empty();
- }
- template<
- typename D = Derived,
- element_layout C = Contiguity,
- typename Enable = std::enable_if_t<C == element_layout::contiguous>>
- constexpr auto data() noexcept(noexcept(std::declval<D &>().begin()))
- -> decltype(std::addressof(*std::declval<D &>().begin()))
- {
- return std::addressof(*derived().begin());
- }
- template<
- typename D = Derived,
- element_layout C = Contiguity,
- typename Enable = std::enable_if_t<C == element_layout::contiguous>>
- constexpr auto data() const
- noexcept(noexcept(std::declval<D const &>().begin()))
- -> decltype(std::addressof(*std::declval<D const &>().begin()))
- {
- return std::addressof(*derived().begin());
- }
- template<typename D = Derived>
- constexpr auto size() noexcept(
- noexcept(std::declval<D &>().end() - std::declval<D &>().begin()))
- -> decltype(std::declval<D &>().end() - std::declval<D &>().begin())
- {
- return derived().end() - derived().begin();
- }
- template<typename D = Derived>
- constexpr auto size() const noexcept(noexcept(
- std::declval<D const &>().end() -
- std::declval<D const &>().begin()))
- -> decltype(
- std::declval<D const &>().end() -
- std::declval<D const &>().begin())
- {
- return derived().end() - derived().begin();
- }
- template<typename D = Derived>
- constexpr auto front() noexcept(noexcept(*std::declval<D &>().begin()))
- -> decltype(*std::declval<D &>().begin())
- {
- return *derived().begin();
- }
- template<typename D = Derived>
- constexpr auto front() const
- noexcept(noexcept(*std::declval<D const &>().begin()))
- -> decltype(*std::declval<D const &>().begin())
- {
- return *derived().begin();
- }
- template<
- typename D = Derived,
- typename Enable = std::enable_if_t<
- v1_dtl::decrementable_sentinel<D>::value &&
- v1_dtl::common_range<D>::value>>
- constexpr auto
- back() noexcept(noexcept(*std::prev(std::declval<D &>().end())))
- -> decltype(*std::prev(std::declval<D &>().end()))
- {
- return *std::prev(derived().end());
- }
- template<
- typename D = Derived,
- typename Enable = std::enable_if_t<
- v1_dtl::decrementable_sentinel<D>::value &&
- v1_dtl::common_range<D>::value>>
- constexpr auto back() const
- noexcept(noexcept(*std::prev(std::declval<D const &>().end())))
- -> decltype(*std::prev(std::declval<D const &>().end()))
- {
- return *std::prev(derived().end());
- }
- template<typename D = Derived>
- constexpr auto operator[](v1_dtl::range_difference_t<D> n) noexcept(
- noexcept(std::declval<D &>().begin()[n]))
- -> decltype(std::declval<D &>().begin()[n])
- {
- return derived().begin()[n];
- }
- template<typename D = Derived>
- constexpr auto operator[](v1_dtl::range_difference_t<D> n) const
- noexcept(noexcept(std::declval<D const &>().begin()[n]))
- -> decltype(std::declval<D const &>().begin()[n])
- {
- return derived().begin()[n];
- }
- };
- /** Implementation of `operator!=()` for all views derived from
- `view_interface`. */
- template<typename ViewInterface>
- constexpr auto operator!=(ViewInterface lhs, ViewInterface rhs) noexcept(
- noexcept(lhs == rhs))
- -> decltype(v1_dtl::derived_view(lhs), !(lhs == rhs))
- {
- return !(lhs == rhs);
- }
- }}}
- #if 201703L < __cplusplus && defined(__cpp_lib_concepts) || \
- defined(BOOST_STL_INTERFACES_DOXYGEN)
- #include <ranges>
- namespace boost { namespace stl_interfaces { namespace v2 {
- /** A template alias for `std::view_interface`. This only exists to make
- migration from Boost.STLInterfaces to C++20 easier; switch to the one
- in `std` as soon as you can. */
- template<typename D, bool = false>
- using view_interface = std::ranges::view_interface<D>;
- }}}
- #endif
- #endif
|