feat():initial version
This commit is contained in:
95
install/boost_1_75_0/include/boost/stl_interfaces/fwd.hpp
Normal file
95
install/boost_1_75_0/include/boost/stl_interfaces/fwd.hpp
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user