feat():initial version

This commit is contained in:
2026-06-09 20:16:47 +08:00
commit 85fbb3188c
14809 changed files with 3044607 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
// 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_FWD_HPP
#define BOOST_STL_INTERFACES_FWD_HPP
#include <iterator>
#ifndef BOOST_STL_INTERFACES_DOXYGEN
#if defined(_MSC_VER) || defined(__GNUC__) && __GNUC__ < 8
#define BOOST_STL_INTERFACES_NO_HIDDEN_FRIEND_CONSTEXPR
#define BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR
#else
#define BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR constexpr
#endif
#if defined(__GNUC__) && __GNUC__ < 9
#define BOOST_STL_INTERFACES_CONCEPT concept bool
#else
#define BOOST_STL_INTERFACES_CONCEPT concept
#endif
#endif
namespace boost { namespace stl_interfaces {
inline namespace v1 {
/** An enumeration used to indicate whether the underlying data have a
contiguous or discontiguous layout when instantiating
`view_interface` and `sequence_container_interface`. */
enum class element_layout : bool {
discontiguous = false,
contiguous = true
};
namespace v1_dtl {
template<typename... T>
using void_t = void;
template<typename Iter>
using iter_difference_t =
typename std::iterator_traits<Iter>::difference_type;
template<typename Range, typename = void>
struct iterator;
template<typename Range>
struct iterator<
Range,
void_t<decltype(std::declval<Range &>().begin())>>
{
using type = decltype(std::declval<Range &>().begin());
};
template<typename Range>
using iterator_t = typename iterator<Range>::type;
template<typename Range, typename = void>
struct sentinel;
template<typename Range>
struct sentinel<
Range,
void_t<decltype(std::declval<Range &>().end())>>
{
using type = decltype(std::declval<Range &>().end());
};
template<typename Range>
using sentinel_t = typename sentinel<Range>::type;
template<typename Range>
using range_difference_t = iter_difference_t<iterator_t<Range>>;
template<typename Range>
using common_range =
std::is_same<iterator_t<Range>, sentinel_t<Range>>;
template<typename Range, typename = void>
struct decrementable_sentinel : std::false_type
{
};
template<typename Range>
struct decrementable_sentinel<
Range,
void_t<decltype(--std::declval<sentinel_t<Range> &>())>>
: std::true_type
{
};
}
}
}}
#endif

View File

@@ -0,0 +1,675 @@
// 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_ITERATOR_INTERFACE_HPP
#define BOOST_STL_INTERFACES_ITERATOR_INTERFACE_HPP
#include <boost/stl_interfaces/fwd.hpp>
#include <utility>
#include <type_traits>
#if defined(__cpp_lib_three_way_comparison)
#include <compare>
#endif
namespace boost { namespace stl_interfaces {
/** A type for granting access to the private members of an iterator
derived from `iterator_interface`. */
struct access
{
#ifndef BOOST_STL_INTERFACES_DOXYGEN
template<typename D>
static constexpr auto base(D & d) noexcept
-> decltype(d.base_reference())
{
return d.base_reference();
}
template<typename D>
static constexpr auto base(D const & d) noexcept
-> decltype(d.base_reference())
{
return d.base_reference();
}
#endif
};
/** The return type of `operator->()` in a proxy iterator.
This template is used as the default `Pointer` template parameter in
the `proxy_iterator_interface` template alias. Note that the use of
this template implies a copy or move of the underlying object of type
`T`. */
template<typename T>
struct proxy_arrow_result
{
constexpr proxy_arrow_result(T const & value) noexcept(
noexcept(T(value))) :
value_(value)
{}
constexpr proxy_arrow_result(T && value) noexcept(
noexcept(T(std::move(value)))) :
value_(std::move(value))
{}
constexpr T const * operator->() const noexcept { return &value_; }
constexpr T * operator->() noexcept { return &value_; }
private:
T value_;
};
namespace detail {
template<typename Pointer, typename T>
auto make_pointer(
T && value,
std::enable_if_t<std::is_pointer<Pointer>::value, int> = 0)
-> decltype(std::addressof(value))
{
return std::addressof(value);
}
template<typename Pointer, typename T>
auto make_pointer(
T && value,
std::enable_if_t<!std::is_pointer<Pointer>::value, int> = 0)
{
return Pointer(std::forward<T>(value));
}
template<typename IteratorConcept>
struct concept_category
{
using type = IteratorConcept;
};
template<typename IteratorConcept>
using concept_category_t =
typename concept_category<IteratorConcept>::type;
template<typename Pointer, typename IteratorConcept>
struct pointer
{
using type = Pointer;
};
template<typename Pointer>
struct pointer<Pointer, std::output_iterator_tag>
{
using type = void;
};
template<typename Pointer, typename IteratorConcept>
using pointer_t = typename pointer<Pointer, IteratorConcept>::type;
template<typename T, typename U>
using interoperable = std::integral_constant<
bool,
(std::is_convertible<T, U>::value ||
std::is_convertible<U, T>::value)>;
template<typename T, typename U>
using common_t =
std::conditional_t<std::is_convertible<T, U>::value, U, T>;
template<typename T>
using use_base = decltype(access::base(std::declval<T &>()));
template<typename... T>
using void_t = void;
template<
typename AlwaysVoid,
template<class...> class Template,
typename... Args>
struct detector : std::false_type
{
};
template<template<class...> class Template, typename... Args>
struct detector<void_t<Template<Args...>>, Template, Args...>
: std::true_type
{
};
template<
typename T,
typename U,
bool UseBase = detector<void, use_base, T>::value>
struct common_eq
{
static constexpr auto call(T lhs, U rhs)
{
return static_cast<common_t<T, U>>(lhs).derived() ==
static_cast<common_t<T, U>>(rhs).derived();
}
};
template<typename T, typename U>
struct common_eq<T, U, true>
{
static constexpr auto call(T lhs, U rhs)
{
return access::base(lhs) == access::base(rhs);
}
};
template<typename T, typename U>
constexpr auto common_diff(T lhs, U rhs) noexcept(noexcept(
static_cast<common_t<T, U>>(lhs) -
static_cast<common_t<T, U>>(rhs)))
-> decltype(
static_cast<common_t<T, U>>(lhs) -
static_cast<common_t<T, U>>(rhs))
{
return static_cast<common_t<T, U>>(lhs) -
static_cast<common_t<T, U>>(rhs);
}
}
}}
namespace boost { namespace stl_interfaces { inline namespace v1 {
/** A CRTP template that one may derive from to make defining iterators
easier.
The template parameter `D` for `iterator_interface` may be an
incomplete type. Before any member of the resulting specialization of
`iterator_interface` other than special member functions is
referenced, `D` shall be complete, and model
`std::derived_from<iterator_interface<D>>`. */
template<
typename Derived,
typename IteratorConcept,
typename ValueType,
typename Reference = ValueType &,
typename Pointer = ValueType *,
typename DifferenceType = std::ptrdiff_t
#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 iterator_interface;
namespace v1_dtl {
template<typename Iterator, typename = void>
struct ra_iter : std::false_type
{
};
template<typename Iterator>
struct ra_iter<Iterator, void_t<typename Iterator::iterator_concept>>
: std::integral_constant<
bool,
std::is_base_of<
std::random_access_iterator_tag,
typename Iterator::iterator_concept>::value>
{
};
template<typename Iterator, typename DifferenceType, typename = void>
struct plus_eq : std::false_type
{
};
template<typename Iterator, typename DifferenceType>
struct plus_eq<
Iterator,
DifferenceType,
void_t<decltype(
std::declval<Iterator &>() += std::declval<DifferenceType>())>>
: std::true_type
{
};
template<
typename D,
typename IteratorConcept,
typename ValueType,
typename Reference,
typename Pointer,
typename DifferenceType>
void derived_iterator(iterator_interface<
D,
IteratorConcept,
ValueType,
Reference,
Pointer,
DifferenceType> const &);
}
template<
typename Derived,
typename IteratorConcept,
typename ValueType,
typename Reference,
typename Pointer,
typename DifferenceType
#ifndef BOOST_STL_INTERFACES_DOXYGEN
,
typename E
#endif
>
struct iterator_interface
{
#ifndef BOOST_STL_INTERFACES_DOXYGEN
private:
constexpr Derived & derived() noexcept
{
return static_cast<Derived &>(*this);
}
constexpr Derived const & derived() const noexcept
{
return static_cast<Derived const &>(*this);
}
template<typename T, typename U, bool UseBase>
friend struct detail::common_eq;
#endif
public:
using iterator_concept = IteratorConcept;
using iterator_category = detail::concept_category_t<iterator_concept>;
using value_type = std::remove_const_t<ValueType>;
using reference = Reference;
using pointer = detail::pointer_t<Pointer, iterator_concept>;
using difference_type = DifferenceType;
template<typename D = Derived>
constexpr auto operator*() const
noexcept(noexcept(*access::base(std::declval<D const &>())))
-> decltype(*access::base(std::declval<D const &>()))
{
return *access::base(derived());
}
template<typename D = Derived>
constexpr auto operator-> () const noexcept(
noexcept(detail::make_pointer<pointer>(*std::declval<D const &>())))
-> decltype(
detail::make_pointer<pointer>(*std::declval<D const &>()))
{
return detail::make_pointer<pointer>(*derived());
}
template<typename D = Derived>
constexpr auto operator[](difference_type i) const noexcept(noexcept(
D(std::declval<D const &>()),
std::declval<D &>() += i,
*std::declval<D &>()))
-> decltype(std::declval<D &>() += i, *std::declval<D &>())
{
D retval = derived();
retval += i;
return *retval;
}
template<
typename D = Derived,
typename Enable =
std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>>
constexpr auto
operator++() noexcept(noexcept(++access::base(std::declval<D &>())))
-> decltype(++access::base(std::declval<D &>()))
{
return ++access::base(derived());
}
template<typename D = Derived>
constexpr auto operator++() noexcept(
noexcept(std::declval<D &>() += difference_type(1)))
-> decltype(
std::declval<D &>() += difference_type(1), std::declval<D &>())
{
derived() += difference_type(1);
return derived();
}
template<typename D = Derived>
constexpr auto operator++(int)noexcept(
noexcept(D(std::declval<D &>()), ++std::declval<D &>()))
-> std::remove_reference_t<decltype(
D(std::declval<D &>()),
++std::declval<D &>(),
std::declval<D &>())>
{
D retval = derived();
++derived();
return retval;
}
template<typename D = Derived>
constexpr auto operator+=(difference_type n) noexcept(
noexcept(access::base(std::declval<D &>()) += n))
-> decltype(access::base(std::declval<D &>()) += n)
{
return access::base(derived()) += n;
}
template<typename D = Derived>
constexpr auto operator+(difference_type i) const
noexcept(noexcept(D(std::declval<D &>()), std::declval<D &>() += i))
-> std::remove_reference_t<decltype(
D(std::declval<D &>()),
std::declval<D &>() += i,
std::declval<D &>())>
{
D retval = derived();
retval += i;
return retval;
}
friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived
operator+(difference_type i, Derived it) noexcept
{
return it + i;
}
template<
typename D = Derived,
typename Enable =
std::enable_if_t<!v1_dtl::plus_eq<D, difference_type>::value>>
constexpr auto
operator--() noexcept(noexcept(--access::base(std::declval<D &>())))
-> decltype(--access::base(std::declval<D &>()))
{
return --access::base(derived());
}
template<typename D = Derived>
constexpr auto operator--() noexcept(noexcept(
D(std::declval<D &>()), std::declval<D &>() += -difference_type(1)))
-> decltype(
std::declval<D &>() += -difference_type(1), std::declval<D &>())
{
derived() += -difference_type(1);
return derived();
}
template<typename D = Derived>
constexpr auto operator--(int)noexcept(
noexcept(D(std::declval<D &>()), --std::declval<D &>()))
-> std::remove_reference_t<decltype(
D(std::declval<D &>()),
--std::declval<D &>(),
std::declval<D &>())>
{
D retval = derived();
--derived();
return retval;
}
template<typename D = Derived>
constexpr D & operator-=(difference_type i) noexcept
{
derived() += -i;
return derived();
}
template<typename D = Derived>
constexpr auto operator-(D other) const noexcept(noexcept(
access::base(std::declval<D const &>()) - access::base(other)))
-> decltype(
access::base(std::declval<D const &>()) - access::base(other))
{
return access::base(derived()) - access::base(other);
}
friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR Derived
operator-(Derived it, difference_type i) noexcept
{
Derived retval = it;
retval += -i;
return retval;
}
};
/** Implementation of `operator==()`, implemented in terms of the iterator
underlying IteratorInterface, for all iterators derived from
`iterator_interface`, except those with an iterator category derived
from `std::random_access_iterator_tag`. */
template<
typename IteratorInterface1,
typename IteratorInterface2,
typename Enable =
std::enable_if_t<!v1_dtl::ra_iter<IteratorInterface1>::value>>
constexpr auto
operator==(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept
-> decltype(
access::base(std::declval<IteratorInterface1 &>()) ==
access::base(std::declval<IteratorInterface2 &>()))
{
return access::base(lhs) == access::base(rhs);
}
/** Implementation of `operator==()` for all iterators derived from
`iterator_interface` that have an iterator category derived from
`std::random_access_iterator_tag`. */
template<
typename IteratorInterface1,
typename IteratorInterface2,
typename Enable =
std::enable_if_t<v1_dtl::ra_iter<IteratorInterface1>::value>>
constexpr auto
operator==(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
noexcept(detail::common_diff(lhs, rhs)))
-> decltype(
v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) == 0)
{
return detail::common_diff(lhs, rhs) == 0;
}
/** Implementation of `operator!=()` for all iterators derived from
`iterator_interface`. */
template<typename IteratorInterface1, typename IteratorInterface2>
constexpr auto operator!=(
IteratorInterface1 lhs,
IteratorInterface2 rhs) noexcept(noexcept(!(lhs == rhs)))
-> decltype(v1_dtl::derived_iterator(lhs), !(lhs == rhs))
{
return !(lhs == rhs);
}
/** Implementation of `operator<()` for all iterators derived from
`iterator_interface` that have an iterator category derived from
`std::random_access_iterator_tag`. */
template<typename IteratorInterface1, typename IteratorInterface2>
constexpr auto
operator<(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
noexcept(detail::common_diff(lhs, rhs)))
-> decltype(
v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) < 0)
{
return detail::common_diff(lhs, rhs) < 0;
}
/** Implementation of `operator<=()` for all iterators derived from
`iterator_interface` that have an iterator category derived from
`std::random_access_iterator_tag`. */
template<typename IteratorInterface1, typename IteratorInterface2>
constexpr auto
operator<=(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
noexcept(detail::common_diff(lhs, rhs)))
-> decltype(
v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) <= 0)
{
return detail::common_diff(lhs, rhs) <= 0;
}
/** Implementation of `operator>()` for all iterators derived from
`iterator_interface` that have an iterator category derived from
`std::random_access_iterator_tag`. */
template<typename IteratorInterface1, typename IteratorInterface2>
constexpr auto
operator>(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
noexcept(detail::common_diff(lhs, rhs)))
-> decltype(
v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) > 0)
{
return detail::common_diff(lhs, rhs) > 0;
}
/** Implementation of `operator>=()` for all iterators derived from
`iterator_interface` that have an iterator category derived from
`std::random_access_iterator_tag`. */
template<typename IteratorInterface1, typename IteratorInterface2>
constexpr auto
operator>=(IteratorInterface1 lhs, IteratorInterface2 rhs) noexcept(
noexcept(detail::common_diff(lhs, rhs)))
-> decltype(
v1_dtl::derived_iterator(lhs), detail::common_diff(lhs, rhs) >= 0)
{
return detail::common_diff(lhs, rhs) >= 0;
}
/** A template alias useful for defining proxy iterators. \see
`iterator_interface`. */
template<
typename Derived,
typename IteratorConcept,
typename ValueType,
typename Reference = ValueType,
typename DifferenceType = std::ptrdiff_t>
using proxy_iterator_interface = iterator_interface<
Derived,
IteratorConcept,
ValueType,
Reference,
proxy_arrow_result<Reference>,
DifferenceType>;
}}}
#if 201703L < __cplusplus && defined(__cpp_lib_ranges)
namespace boost { namespace stl_interfaces { namespace v2 { namespace detail {
template<typename Iterator>
struct iter_concept;
template<typename Iterator>
requires requires
{
typename std::iterator_traits<Iterator>::iterator_concept;
}
struct iter_concept<Iterator>
{
using type = typename std::iterator_traits<Iterator>::iterator_concept;
};
template<typename Iterator>
requires(
!requires {
typename std::iterator_traits<Iterator>::iterator_concept;
} &&
requires {
typename std::iterator_traits<Iterator>::iterator_category;
}) struct iter_concept<Iterator>
{
using type = typename std::iterator_traits<Iterator>::iterator_category;
};
template<typename Iterator>
requires(
!requires {
typename std::iterator_traits<Iterator>::iterator_concept;
} &&
!requires {
typename std::iterator_traits<Iterator>::iterator_category;
}) struct iter_concept<Iterator>
{
using type = std::random_access_iterator_tag;
};
template<typename Iterator>
struct iter_concept
{};
template<typename Iterator>
using iter_concept_t = typename iter_concept<Iterator>::type;
}}}}
#endif
#ifdef BOOST_STL_INTERFACES_DOXYGEN
/** `static_asserts` that type `type` models concept `concept_name`. This is
useful for checking that an iterator, view, etc. that you write using one
of the *`_interface` templates models the right C++ concept.
For example: `BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(my_iter,
std::input_iterator)`.
\note This macro expands to nothing when `__cpp_lib_concepts` is not
defined. */
#define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(type, concept_name)
/** `static_asserts` that the types of all typedefs in
`std::iterator_traits<iter>` match the remaining macro parameters. This
is useful for checking that an iterator you write using
`iterator_interface` has the correct iterator traits.
For example: `BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(my_iter,
std::input_iterator_tag, std::input_iterator_tag, int, int &, int *, std::ptrdiff_t)`.
\note This macro ignores the `concept` parameter when `__cpp_lib_concepts`
is not defined. */
#define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \
iter, category, concept, value_type, reference, pointer, difference_type)
#else
#define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_CONCEPT_IMPL( \
type, concept_name) \
static_assert(concept_name<type>, "");
#define BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(iter, concept_name)
#define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
iter, category, value_t, ref, ptr, diff_t) \
static_assert( \
std::is_same< \
typename std::iterator_traits<iter>::iterator_category, \
category>::value, \
""); \
static_assert( \
std::is_same< \
typename std::iterator_traits<iter>::value_type, \
value_t>::value, \
""); \
static_assert( \
std::is_same<typename std::iterator_traits<iter>::reference, ref>:: \
value, \
""); \
static_assert( \
std::is_same<typename std::iterator_traits<iter>::pointer, ptr>:: \
value, \
""); \
static_assert( \
std::is_same< \
typename std::iterator_traits<iter>::difference_type, \
diff_t>::value, \
"");
#if 201703L < __cplusplus && defined(__cpp_lib_ranges)
#define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \
iter, category, concept, value_type, reference, pointer, difference_type) \
static_assert( \
std::is_same_v< \
boost::stl_interfaces::v2::detail::iter_concept_t<iter>, \
concept>, \
""); \
BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
iter, category, value_type, reference, pointer, difference_type)
#else
#define BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( \
iter, category, concept, value_type, reference, pointer, difference_type) \
BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS_IMPL( \
iter, category, value_type, reference, pointer, difference_type)
#endif
#endif
#endif

View File

@@ -0,0 +1,198 @@
// 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_REVERSE_ITERATOR_HPP
#define BOOST_STL_INTERFACES_REVERSE_ITERATOR_HPP
#include <boost/stl_interfaces/iterator_interface.hpp>
namespace boost { namespace stl_interfaces { inline namespace v1 {
namespace v1_dtl {
template<typename Iter>
constexpr auto ce_dist(Iter f, Iter l, std::random_access_iterator_tag)
-> decltype(l - f)
{
return l - f;
}
template<typename Iter, typename Tag>
constexpr auto ce_dist(Iter f, Iter l, Tag)
-> decltype(std::distance(f, l))
{
decltype(std::distance(f, l)) retval = 0;
for (; f != l; ++f) {
++retval;
}
return retval;
}
template<typename Iter>
constexpr Iter ce_prev(Iter it)
{
return --it;
}
template<typename Iter, typename Offset>
constexpr void
ce_adv(Iter & f, Offset n, std::random_access_iterator_tag)
{
f += n;
}
template<typename Iter, typename Offset, typename Tag>
constexpr void ce_adv(Iter & f, Offset n, Tag)
{
if (0 < n) {
for (Offset i = 0; i < n; ++i) {
++f;
}
} else {
for (Offset i = 0; i < -n; ++i) {
--f;
}
}
}
}
/** This type is very similar to the C++20 version of
`std::reverse_iterator`; it is `constexpr`-, `noexcept`-, and
proxy-friendly. */
template<typename BidiIter>
struct reverse_iterator
: iterator_interface<
reverse_iterator<BidiIter>,
#if 201703L < __cplusplus && defined(__cpp_lib_ranges)
typename v2::detail::iter_concept_t<BidiIter>,
#else
typename std::iterator_traits<BidiIter>::iterator_category,
#endif
typename std::iterator_traits<BidiIter>::value_type,
typename std::iterator_traits<BidiIter>::reference,
typename std::iterator_traits<BidiIter>::pointer,
typename std::iterator_traits<BidiIter>::difference_type>
{
constexpr reverse_iterator() noexcept(noexcept(BidiIter())) : it_() {}
constexpr reverse_iterator(BidiIter it) noexcept(
noexcept(BidiIter(it))) :
it_(it)
{}
template<
typename BidiIter2,
typename E = std::enable_if_t<
std::is_convertible<BidiIter2, BidiIter>::value>>
reverse_iterator(reverse_iterator<BidiIter2> const & it) : it_(it.it_)
{}
friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR auto
operator-(reverse_iterator lhs, reverse_iterator rhs) noexcept(
noexcept(v1_dtl::ce_dist(
lhs.it_,
rhs.it_,
typename std::iterator_traits<BidiIter>::iterator_category{})))
{
return -v1_dtl::ce_dist(
rhs.it_,
lhs.it_,
typename std::iterator_traits<BidiIter>::iterator_category{});
}
constexpr typename std::iterator_traits<BidiIter>::reference
operator*() const noexcept(
noexcept(std::prev(v1_dtl::ce_prev(std::declval<BidiIter &>()))))
{
return *v1_dtl::ce_prev(it_);
}
constexpr reverse_iterator & operator+=(
typename std::iterator_traits<BidiIter>::difference_type
n) noexcept(noexcept(v1_dtl::
ce_adv(
std::declval<BidiIter &>(),
-n,
typename std::iterator_traits<
BidiIter>::
iterator_category{})))
{
v1_dtl::ce_adv(
it_,
-n,
typename std::iterator_traits<BidiIter>::iterator_category{});
return *this;
}
constexpr BidiIter base() const noexcept { return it_; }
private:
friend access;
constexpr BidiIter & base_reference() noexcept { return it_; }
constexpr BidiIter const & base_reference() const noexcept
{
return it_;
}
template<typename BidiIter2>
friend struct reverse_iterator;
BidiIter it_;
};
template<typename BidiIter>
constexpr auto operator==(
reverse_iterator<BidiIter> lhs,
reverse_iterator<BidiIter>
rhs) noexcept(noexcept(lhs.base() == rhs.base()))
-> decltype(rhs.base() == lhs.base())
{
return lhs.base() == rhs.base();
}
template<typename BidiIter1, typename BidiIter2>
constexpr auto operator==(
reverse_iterator<BidiIter1> lhs,
reverse_iterator<BidiIter2>
rhs) noexcept(noexcept(lhs.base() == rhs.base()))
-> decltype(rhs.base() == lhs.base())
{
return lhs.base() == rhs.base();
}
/** Makes a `reverse_iterator<BidiIter>` from an iterator of type
`Bidiiter`. */
template<typename BidiIter>
auto make_reverse_iterator(BidiIter it)
{
return reverse_iterator<BidiIter>(it);
}
}}}
#if 201703L < __cplusplus && defined(__cpp_lib_concepts) || \
defined(BOOST_STL_INTERFACES_DOXYGEN)
namespace boost { namespace stl_interfaces { namespace v2 {
/** A template alias for `std::reverse_iterator`. 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 BidiIter>
using reverse_iterator = std::reverse_iterator<BidiIter>;
/** Makes a `reverse_iterator<BidiIter>` from an iterator of type
`Bidiiter`. 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 BidiIter>
auto make_reverse_iterator(BidiIter it)
{
return reverse_iterator<BidiIter>(it);
}
}}}
#endif
#endif

View File

@@ -0,0 +1,676 @@
// 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_CONTAINER_INTERFACE_HPP
#define BOOST_STL_INTERFACES_CONTAINER_INTERFACE_HPP
#include <boost/stl_interfaces/reverse_iterator.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <algorithm>
#include <stdexcept>
#include <cstddef>
namespace boost { namespace stl_interfaces { namespace detail {
template<typename T, typename SizeType>
struct n_iter : iterator_interface<
n_iter<T, SizeType>,
std::random_access_iterator_tag,
T>
{
n_iter() : x_(nullptr), n_(0) {}
n_iter(T const & x, SizeType n) : x_(&x), n_(n) {}
constexpr std::ptrdiff_t operator-(n_iter other) const noexcept
{
return std::ptrdiff_t(n_) - std::ptrdiff_t(other.n_);
}
n_iter & operator+=(std::ptrdiff_t offset)
{
n_ += offset;
return *this;
}
private:
friend access;
constexpr T const *& base_reference() noexcept { return x_; }
constexpr T const * base_reference() const noexcept { return x_; }
T const * x_;
SizeType n_;
};
template<typename T, typename SizeType>
constexpr auto make_n_iter(T const & x, SizeType n) noexcept(
noexcept(n_iter<T, SizeType>(x, n)))
{
using result_type = n_iter<T, SizeType>;
return result_type(x, SizeType(0));
}
template<typename T, typename SizeType>
constexpr auto make_n_iter_end(T const & x, SizeType n) noexcept(
noexcept(n_iter<T, SizeType>(x, n)))
{
return n_iter<T, SizeType>(x, n);
}
template<typename Container>
std::size_t fake_capacity(Container const & c)
{
return SIZE_MAX;
}
template<
typename Container,
typename Enable = decltype(
std::size_t() = std::declval<Container const &>().capacity())>
std::size_t fake_capacity(Container const & c)
{
return c.capacity();
}
}}}
namespace boost { namespace stl_interfaces { inline namespace v1 {
/** A CRTP template that one may derive from to make it easier to define
container types.
The template parameter `D` for `sequence_container_interface` may be
an incomplete type. Before any member of the resulting specialization
of `sequence_container_interface` other than special member functions
is referenced, `D` shall be complete; shall model
`std::derived_from<sequence_container_interface<D>>`,
`std::semiregular`, and `std::forward_range`; and shall contain all
the nested types required in Table 72: Container requirements and, for
those whose iterator nested type models `std::bidirectinal_iterator`,
those in Table 73: Reversible container requirements.
For an object `d` of type `D`, a call to `std::ranges::begin(d)` sxhall
not mutate any data members of `d`, and `d`'s destructor shall end the
lifetimes of the objects in `[std::ranges::begin(d),
std::ranges::end(d))`. */
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 sequence_container_interface;
namespace v1_dtl {
template<typename Iter>
using in_iter = std::is_convertible<
typename std::iterator_traits<Iter>::iterator_category,
std::input_iterator_tag>;
template<typename D, typename = void>
struct clear_impl
{
static constexpr void call(D & d) noexcept {}
};
template<typename D>
struct clear_impl<D, void_t<decltype(std::declval<D>().clear())>>
{
static constexpr void call(D & d) noexcept { d.clear(); }
};
template<typename D, element_layout Contiguity>
void derived_container(sequence_container_interface<D, Contiguity> const &);
}
template<
typename Derived,
element_layout Contiguity
#ifndef BOOST_STL_INTERFACES_DOXYGEN
,
typename E
#endif
>
struct sequence_container_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);
}
constexpr Derived & mutable_derived() const noexcept
{
return const_cast<Derived &>(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,
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()
#if !BOOST_CLANG
noexcept(noexcept(
std::declval<D &>().end() - std::declval<D &>().begin()))
#endif
-> decltype(typename D::size_type(
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(typename D::size_type(
#if !BOOST_CLANG
std::declval<D const &>().end() -
std::declval<D const &>().begin()
#endif
))
{
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>
constexpr auto push_front(typename D::value_type const & x) noexcept(
noexcept(std::declval<D &>().emplace_front(x)))
-> decltype((void)std::declval<D &>().emplace_front(x))
{
derived().emplace_front(x);
}
template<typename D = Derived>
constexpr auto push_front(typename D::value_type && x) noexcept(
noexcept(std::declval<D &>().emplace_front(std::move(x))))
-> decltype((void)std::declval<D &>().emplace_front(std::move(x)))
{
derived().emplace_front(std::move(x));
}
template<typename D = Derived>
constexpr auto pop_front() noexcept -> decltype(
std::declval<D &>().emplace_front(
std::declval<typename D::value_type &>()),
(void)std::declval<D &>().erase(std::declval<D &>().begin()))
{
derived().erase(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 push_back(typename D::value_type const & x) noexcept(
noexcept(std::declval<D &>().emplace_back(x)))
-> decltype((void)std::declval<D &>().emplace_back(x))
{
derived().emplace_back(x);
}
template<typename D = Derived>
constexpr auto push_back(typename D::value_type && x) noexcept(
noexcept(std::declval<D &>().emplace_back(std::move(x))))
-> decltype((void)std::declval<D &>().emplace_back(std::move(x)))
{
derived().emplace_back(std::move(x));
}
template<typename D = Derived>
constexpr auto pop_back() noexcept -> decltype(
std::declval<D &>().emplace_back(
std::declval<typename D::value_type &>()),
(void)std::declval<D &>().erase(
std::prev(std::declval<D &>().end())))
{
derived().erase(std::prev(derived().end()));
}
template<typename D = Derived>
constexpr auto operator[](typename D::size_type 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[](typename D::size_type n) const
noexcept(noexcept(std::declval<D const &>().begin()[n]))
-> decltype(std::declval<D const &>().begin()[n])
{
return derived().begin()[n];
}
template<typename D = Derived>
constexpr auto at(typename D::size_type i)
-> decltype(std::declval<D &>().size(), std::declval<D &>()[i])
{
if (derived().size() <= i) {
throw std::out_of_range(
"Bounds check failed in sequence_container_interface::at()");
}
return derived()[i];
}
template<typename D = Derived>
constexpr auto at(typename D::size_type i) const -> decltype(
std::declval<D const &>().size(), std::declval<D const &>()[i])
{
if (derived().size() <= i) {
throw std::out_of_range(
"Bounds check failed in sequence_container_interface::at()");
}
return derived()[i];
}
template<typename D = Derived, typename Iter = typename D::const_iterator>
constexpr Iter begin() const
noexcept(noexcept(std::declval<D &>().begin()))
{
return Iter(mutable_derived().begin());
}
template<typename D = Derived, typename Iter = typename D::const_iterator>
constexpr Iter end() const noexcept(noexcept(std::declval<D &>().end()))
{
return Iter(mutable_derived().end());
}
template<typename D = Derived>
constexpr auto cbegin() const
noexcept(noexcept(std::declval<D const &>().begin()))
-> decltype(std::declval<D const &>().begin())
{
return derived().begin();
}
template<typename D = Derived>
constexpr auto cend() const
noexcept(noexcept(std::declval<D const &>().end()))
-> decltype(std::declval<D const &>().end())
{
return derived().end();
}
template<
typename D = Derived,
typename Enable = std::enable_if_t<v1_dtl::common_range<D>::value>>
constexpr auto rbegin() noexcept(noexcept(
stl_interfaces::make_reverse_iterator(std::declval<D &>().end())))
{
return stl_interfaces::make_reverse_iterator(derived().end());
}
template<
typename D = Derived,
typename Enable = std::enable_if_t<v1_dtl::common_range<D>::value>>
constexpr auto rend() noexcept(noexcept(
stl_interfaces::make_reverse_iterator(std::declval<D &>().begin())))
{
return stl_interfaces::make_reverse_iterator(derived().begin());
}
template<typename D = Derived>
constexpr auto rbegin() const
noexcept(noexcept(std::declval<D &>().rbegin()))
{
return
typename D::const_reverse_iterator(mutable_derived().rbegin());
}
template<typename D = Derived>
constexpr auto rend() const
noexcept(noexcept(std::declval<D &>().rend()))
{
return typename D::const_reverse_iterator(mutable_derived().rend());
}
template<typename D = Derived>
constexpr auto crbegin() const
noexcept(noexcept(std::declval<D const &>().rbegin()))
-> decltype(std::declval<D const &>().rbegin())
{
return derived().rbegin();
}
template<typename D = Derived>
constexpr auto crend() const
noexcept(noexcept(std::declval<D const &>().rend()))
-> decltype(std::declval<D const &>().rend())
{
return derived().rend();
}
template<typename D = Derived>
constexpr auto insert(
typename D::const_iterator pos,
typename D::value_type const &
x) noexcept(noexcept(std::declval<D &>().emplace(pos, x)))
-> decltype(std::declval<D &>().emplace(pos, x))
{
return derived().emplace(pos, x);
}
template<typename D = Derived>
constexpr auto insert(
typename D::const_iterator pos,
typename D::value_type &&
x) noexcept(noexcept(std::declval<D &>()
.emplace(pos, std::move(x))))
-> decltype(std::declval<D &>().emplace(pos, std::move(x)))
{
return derived().emplace(pos, std::move(x));
}
template<typename D = Derived>
constexpr auto insert(
typename D::const_iterator pos,
typename D::size_type n,
typename D::value_type const & x)
// If you see an error in this noexcept() expression, that's
// because this function is not properly constrained. In other
// words, Derived does not have a "range" insert like
// insert(position, first, last). If that is the case, this
// function should be removed via SFINAE from overload resolution.
// However, both the trailing decltype code below and a
// std::enable_if in the template parameters do not work. Sorry
// about that. See below for details.
noexcept(noexcept(std::declval<D &>().insert(
pos, detail::make_n_iter(x, n), detail::make_n_iter_end(x, n))))
// This causes the compiler to infinitely recurse into this function's
// declaration, even though the call below does not match the
// signature of this function.
#if 0
-> decltype(std::declval<D &>().insert(
pos, detail::make_n_iter(x, n), detail::make_n_iter_end(x, n)))
#endif
{
return derived().insert(
pos, detail::make_n_iter(x, n), detail::make_n_iter_end(x, n));
}
template<typename D = Derived>
constexpr auto insert(
typename D::const_iterator pos,
std::initializer_list<typename D::value_type>
il) noexcept(noexcept(std::declval<D &>()
.insert(pos, il.begin(), il.end())))
-> decltype(std::declval<D &>().insert(pos, il.begin(), il.end()))
{
return derived().insert(pos, il.begin(), il.end());
}
template<typename D = Derived>
constexpr auto erase(typename D::const_iterator pos) noexcept
-> decltype(std::declval<D &>().erase(pos, std::next(pos)))
{
return derived().erase(pos, std::next(pos));
}
template<
typename InputIterator,
typename D = Derived,
typename Enable =
std::enable_if_t<v1_dtl::in_iter<InputIterator>::value>>
constexpr auto assign(InputIterator first, InputIterator last) noexcept(
noexcept(std::declval<D &>().insert(
std::declval<D &>().begin(), first, last)))
-> decltype(
std::declval<D &>().erase(
std::declval<D &>().begin(), std::declval<D &>().end()),
(void)std::declval<D &>().insert(
std::declval<D &>().begin(), first, last))
{
auto out = derived().begin();
auto const out_last = derived().end();
for (; out != out_last && first != last; ++first, ++out) {
*out = *first;
}
if (out != out_last)
derived().erase(out, out_last);
if (first != last)
derived().insert(derived().end(), first, last);
}
template<typename D = Derived>
constexpr auto assign(
typename D::size_type n,
typename D::value_type const &
x) noexcept(noexcept(std::declval<D &>()
.insert(
std::declval<D &>().begin(),
detail::make_n_iter(x, n),
detail::make_n_iter_end(x, n))))
-> decltype(
std::declval<D &>().size(),
std::declval<D &>().erase(
std::declval<D &>().begin(), std::declval<D &>().end()),
(void)std::declval<D &>().insert(
std::declval<D &>().begin(),
detail::make_n_iter(x, n),
detail::make_n_iter_end(x, n)))
{
if (detail::fake_capacity(derived()) < n) {
Derived temp(n, x);
derived().swap(temp);
} else {
auto const min_size =
std::min<std::ptrdiff_t>(n, derived().size());
auto const fill_end =
std::fill_n(derived().begin(), min_size, x);
if (min_size < (std::ptrdiff_t)derived().size()) {
derived().erase(fill_end, derived().end());
} else {
n -= min_size;
derived().insert(
derived().begin(),
detail::make_n_iter(x, n),
detail::make_n_iter_end(x, n));
}
}
}
template<typename D = Derived>
constexpr auto
assign(std::initializer_list<typename D::value_type> il) noexcept(
noexcept(std::declval<D &>().assign(il.begin(), il.end())))
-> decltype((void)std::declval<D &>().assign(il.begin(), il.end()))
{
derived().assign(il.begin(), il.end());
}
template<typename D = Derived>
constexpr auto
operator=(std::initializer_list<typename D::value_type> il) noexcept(
noexcept(std::declval<D &>().assign(il.begin(), il.end())))
-> decltype(
std::declval<D &>().assign(il.begin(), il.end()),
std::declval<D &>())
{
derived().assign(il.begin(), il.end());
return *this;
}
template<typename D = Derived>
constexpr auto clear() noexcept
-> decltype((void)std::declval<D &>().erase(
std::declval<D &>().begin(), std::declval<D &>().end()))
{
derived().erase(derived().begin(), derived().end());
}
};
/** Implementation of free function `swap()` for all containers derived
from `sequence_container_interface`. */
template<typename ContainerInterface>
constexpr auto swap(
ContainerInterface & lhs,
ContainerInterface & rhs) noexcept(noexcept(lhs.swap(rhs)))
-> decltype(v1_dtl::derived_container(lhs), lhs.swap(rhs))
{
return lhs.swap(rhs);
}
/** Implementation of `operator==()` for all containers derived from
`sequence_container_interface`. */
template<typename ContainerInterface>
constexpr auto
operator==(ContainerInterface const & lhs, ContainerInterface const & rhs) noexcept(
noexcept(lhs.size() == rhs.size()) &&
noexcept(*lhs.begin() == *rhs.begin()))
-> decltype(
v1_dtl::derived_container(lhs),
lhs.size() == rhs.size(),
*lhs.begin() == *rhs.begin(),
true)
{
return lhs.size() == rhs.size() &&
std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
/** Implementation of `operator!=()` for all containers derived from
`sequence_container_interface`. */
template<typename ContainerInterface>
constexpr auto operator!=(
ContainerInterface const & lhs,
ContainerInterface const & rhs) noexcept(noexcept(lhs == rhs))
-> decltype(v1_dtl::derived_container(lhs), lhs == rhs)
{
return !(lhs == rhs);
}
/** Implementation of `operator<()` for all containers derived from
`sequence_container_interface`. */
template<typename ContainerInterface>
constexpr auto operator<(
ContainerInterface const & lhs,
ContainerInterface const &
rhs) noexcept(noexcept(*lhs.begin() < *rhs.begin()))
-> decltype(
v1_dtl::derived_container(lhs), *lhs.begin() < *rhs.begin(), true)
{
auto it1 = lhs.begin();
auto const last1 = lhs.end();
auto it2 = rhs.begin();
auto const last2 = rhs.end();
for (; it1 != last1 && it2 != last2; ++it1, ++it2) {
if (*it1 < *it2)
return true;
if (*it2 < *it1)
return false;
}
return it1 == last1 && it2 != last2;
}
/** Implementation of `operator<=()` for all containers derived from
`sequence_container_interface`. */
template<typename ContainerInterface>
constexpr auto operator<=(
ContainerInterface const & lhs,
ContainerInterface const & rhs) noexcept(noexcept(lhs < rhs))
-> decltype(v1_dtl::derived_container(lhs), lhs < rhs)
{
return !(rhs < lhs);
}
/** Implementation of `operator>()` for all containers derived from
`sequence_container_interface`. */
template<typename ContainerInterface>
constexpr auto operator>(
ContainerInterface const & lhs,
ContainerInterface const & rhs) noexcept(noexcept(lhs < rhs))
-> decltype(v1_dtl::derived_container(lhs), lhs < rhs)
{
return rhs < lhs;
}
/** Implementation of `operator>=()` for all containers derived from
`sequence_container_interface`. */
template<typename ContainerInterface>
constexpr auto operator>=(
ContainerInterface const & lhs,
ContainerInterface const & rhs) noexcept(noexcept(lhs < rhs))
-> decltype(v1_dtl::derived_container(lhs), lhs < rhs)
{
return !(lhs < rhs);
}
}}}
#endif

View File

@@ -0,0 +1,221 @@
// 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