update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -0,0 +1,48 @@
// Copyright (C) 2020 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_CONFIG_HPP
#define BOOST_STL_INTERFACES_CONFIG_HPP
// Included for definition of __cpp_lib_concepts.
#include <iterator>
#if defined(__cpp_lib_concepts) && defined(__cpp_lib_ranges) && \
!defined(BOOST_STL_INTERFACES_DISABLE_CONCEPTS)
#define BOOST_STL_INTERFACES_USE_CONCEPTS 1
#else
#define BOOST_STL_INTERFACES_USE_CONCEPTS 0
#endif
#if defined(__cpp_explicit_this_parameter) && \
BOOST_STL_INTERFACES_USE_CONCEPTS && \
!defined(BOOST_STL_INTERFACES_DISABLE_DEDUCED_THIS)
#define BOOST_STL_INTERFACES_USE_DEDUCED_THIS 1
#else
#define BOOST_STL_INTERFACES_USE_DEDUCED_THIS 0
#endif
// The inline namespaces v1, v2, and v3 represent C++14, C++20, and C++23 and
// later, respectively. v1 is inline for standards before C++20, and v2 is
// inline for C++20 and later. Note that this only applies to code for which
// multiple vI namespace alternatives exist. For example, some instances of
// the v1 namespace may still be inline, if there is no v2 version of its
// contents.
#if !BOOST_STL_INTERFACES_USE_CONCEPTS && !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
# define BOOST_STL_INTERFACES_NAMESPACE_V1 inline namespace v1
# define BOOST_STL_INTERFACES_NAMESPACE_V2 namespace v2
# define BOOST_STL_INTERFACES_NAMESPACE_V3 namespace v3
#elif BOOST_STL_INTERFACES_USE_CONCEPTS && !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
# define BOOST_STL_INTERFACES_NAMESPACE_V1 namespace v1
# define BOOST_STL_INTERFACES_NAMESPACE_V2 inline namespace v2
# define BOOST_STL_INTERFACES_NAMESPACE_V3 namespace v3
#else
# define BOOST_STL_INTERFACES_NAMESPACE_V1 namespace v1
# define BOOST_STL_INTERFACES_NAMESPACE_V2 namespace v2
# define BOOST_STL_INTERFACES_NAMESPACE_V3 inline namespace v3
#endif
#endif

View File

@@ -0,0 +1,148 @@
// Copyright (C) 2022 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_DETAIL_PIPEABLE_VIEW_HPP
#define BOOST_STL_INTERFACES_DETAIL_PIPEABLE_VIEW_HPP
#include <boost/stl_interfaces/config.hpp>
#include <type_traits>
namespace boost { namespace stl_interfaces { namespace detail {
template<typename T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
struct pipeable_base;
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<typename T>
concept pipeable_ = std::derived_from<T, pipeable_base> &&
std::is_object_v<T> && std::copy_constructible<T>;
#else
template<typename T>
constexpr bool pipeable_ = std::is_base_of<pipeable_base, T>::value &&
std::is_object<T>::value && std::is_copy_constructible<T>::value;
#endif
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<pipeable_ T, pipeable_ U>
#else
template<
typename T,
typename U,
typename Enable = std::enable_if_t<pipeable_<T> && pipeable_<U>>>
#endif
struct view_pipeline;
struct pipeable_base
{
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<pipeable_ T, pipeable_ U>
requires std::constructible_from<std::remove_cvref_t<T>, T> &&
std::constructible_from<std::remove_cvref_t<U>, U>
#else
template<
typename T,
typename U,
typename Enable = std::enable_if_t<
pipeable_<T> && pipeable_<U> &&
std::is_constructible<remove_cvref_t<T>, T>::value &&
std::is_constructible<remove_cvref_t<U>, U>::value>>
#endif
friend constexpr auto operator|(T && t, U && u)
{
return view_pipeline<T, U>{(T &&) t, (U &&) u};
}
};
template<typename Derived>
struct pipeable : pipeable_base
{
template<typename R>
friend constexpr auto operator|(R && r, Derived & d)
-> decltype(((Derived &&) d)((R &&) r))
{
return ((Derived &&) d)((R &&) r);
}
template<typename R>
friend constexpr auto operator|(R && r, Derived const & d)
-> decltype(((Derived &&) d)((R &&) r))
{
return ((Derived &&) d)((R &&) r);
}
template<typename R>
friend constexpr auto operator|(R && r, Derived && d)
-> decltype(((Derived &&) d)((R &&) r))
{
return ((Derived &&) d)((R &&) r);
}
};
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<pipeable_ T, pipeable_ U>
#else
template<typename T, typename U, typename>
#endif
struct view_pipeline : pipeable<view_pipeline<T, U>>
{
view_pipeline() = default;
constexpr view_pipeline(T && t, U && u) :
left_(std::move(t)), right_(std::move(u))
{}
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::viewable_range R>
requires std::invocable<T &, R> &&
std::invocable<U &, std::invoke_result_t<T &, R>>
constexpr decltype(auto) operator()(R && r) &
#else
template<typename R>
constexpr auto
operator()(R && r) & -> decltype(this->right_(this->left_((R &&) r)))
#endif
{
return right_(left_((R &&) r));
}
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::viewable_range R>
requires std::invocable<T const &, R> &&
std::invocable<U const &, std::invoke_result_t<T const &, R>>
constexpr decltype(auto) operator()(R && r) const &
#else
template<typename R>
constexpr auto operator()(
R && r) const & -> decltype(this->right_(this->left_((R &&) r)))
#endif
{
return right_(left_((R &&) r));
}
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::viewable_range R>
requires std::invocable<T, R> &&
std::invocable<U, std::invoke_result_t<T, R>>
constexpr decltype(auto) operator()(R && r) &&
#else
template<typename R>
constexpr auto operator()(R && r) && -> decltype(std::move(
this->right_)(std::move(this->left_)((R &&) r)))
#endif
{
return std::move(right_)(std::move(left_)((R &&) r));
}
T left_;
U right_;
};
}}}
#endif

View File

@@ -0,0 +1,107 @@
// Copyright (C) 2022 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_DETAIL_VIEW_CLOSURE_HPP
#define BOOST_STL_INTERFACES_DETAIL_VIEW_CLOSURE_HPP
#include <boost/stl_interfaces/detail/pipeable_view.hpp>
#include <utility>
namespace boost { namespace stl_interfaces { namespace detail {
template<std::size_t I, typename T>
struct box
{
T value_;
};
template<typename Indices, typename Func, typename... T>
struct view_closure_impl;
template<std::size_t... I, typename Func, typename... T>
struct view_closure_impl<std::index_sequence<I...>, Func, T...>
: box<I, T>...
{
view_closure_impl() = default;
constexpr explicit view_closure_impl(Func, T &&... x) :
box<I, T>{std::move(x)}...
{}
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::input_range R>
requires std::ranges::viewable_range<R> &&
std::invocable<Func, R, T &...> &&
std::ranges::view<std::invoke_result_t<Func, R, T &...>>
constexpr auto operator()(R && r) &
#else
template<typename R>
constexpr auto operator()(R && r) & -> decltype(
Func{}((R &&) r, std::declval<box<I, T> &>().value_...))
#endif
{
return Func{}((R &&) r, static_cast<box<I, T> &>(*this).value_...);
}
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::input_range R>
requires std::ranges::viewable_range<R> &&
std::invocable<Func, R, T const &...> &&
std::ranges::view<std::invoke_result_t<Func, R, T const &...>>
constexpr auto operator()(R && r) const &
#else
template<typename R>
constexpr auto operator()(R && r) const & -> decltype(
Func{}((R &&) r, std::declval<box<I, T> const &>().value_...))
#endif
{
return Func{}(
(R &&) r, static_cast<box<I, T> const &>(*this).value_...);
}
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<std::ranges::input_range R>
requires std::ranges::viewable_range<R> &&
std::invocable<Func, R, T...> &&
std::ranges::view<std::invoke_result_t<Func, R, T...>>
constexpr auto operator()(R && r) &&
#else
template<typename R>
constexpr auto operator()(R && r) && -> decltype(
Func{}((R &&) r, std::declval<box<I, T> &&>().value_...))
#endif
{
return Func{}((R &&) r, static_cast<box<I, T> &&>(*this).value_...);
}
};
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<std::semiregular Func, std::copy_constructible... T>
#else
template<typename Func, typename... T>
#endif
struct view_closure
: pipeable<view_closure<Func, T...>>,
view_closure_impl<std::index_sequence_for<T...>, Func, T...>
{
using base_type =
view_closure_impl<std::index_sequence_for<T...>, Func, T...>;
view_closure() = default;
constexpr explicit view_closure(Func func, T &&... x) :
base_type{func, std::move(x)...}
{}
};
#if defined(__cpp_deduction_guides)
template<typename Func, typename... T>
view_closure(Func, T...) -> view_closure<Func, T...>;
#endif
}}}
#endif

View File

@@ -0,0 +1,103 @@
// 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 <boost/stl_interfaces/config.hpp>
#if BOOST_STL_INTERFACES_USE_CONCEPTS
#include <ranges>
#endif
#if defined(__cpp_lib_three_way_comparison)
#include <compare>
#endif
#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 {
/** 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
};
BOOST_STL_INTERFACES_NAMESPACE_V1 {
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

File diff suppressed because it is too large Load Diff

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_REVERSE_ITERATOR_HPP
#define BOOST_STL_INTERFACES_REVERSE_ITERATOR_HPP
#include <boost/stl_interfaces/iterator_interface.hpp>
namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_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<
#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
reverse_iterator<BidiIter>,
#endif
#if BOOST_STL_INTERFACES_USE_CONCEPTS
typename boost::stl_interfaces::v2::v2_dtl::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 defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
namespace boost { namespace stl_interfaces { BOOST_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);
}
}}}
namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 {
/** 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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,318 @@
// Copyright (C) 2022 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_ADAPTOR_HPP
#define BOOST_STL_INTERFACES_VIEW_ADAPTOR_HPP
#include <boost/stl_interfaces/config.hpp>
#include <boost/stl_interfaces/detail/view_closure.hpp>
#include <boost/type_traits/is_detected.hpp>
#include <tuple>
#include <type_traits>
#if !defined(BOOST_STL_INTERFACES_DOXYGEN)
#if defined(__cpp_lib_ranges) && 202202L <= __cpp_lib_ranges
#define BOOST_STL_INTERFACES_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE 1
#else
#define BOOST_STL_INTERFACES_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE 0
#endif
#if !BOOST_STL_INTERFACES_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE && \
BOOST_STL_INTERFACES_USE_CONCEPTS && defined(__GNUC__) && 12 <= __GNUC__
#define BOOST_STL_INTERFACES_USE_LIBSTDCPP_GCC12_RANGE_ADAPTOR_CLOSURE 1
#else
#define BOOST_STL_INTERFACES_USE_LIBSTDCPP_GCC12_RANGE_ADAPTOR_CLOSURE 0
#endif
#if !BOOST_STL_INTERFACES_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE && \
defined(_MSC_VER) && _MSC_VER <= 1929
#define BOOST_STL_INTERFACES_NEED_VS_COMPATIBLE_RANGE_ADAPTOR_CLOSURE 1
#else
#define BOOST_STL_INTERFACES_NEED_VS_COMPATIBLE_RANGE_ADAPTOR_CLOSURE 0
#endif
#if !BOOST_STL_INTERFACES_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE && \
!BOOST_STL_INTERFACES_USE_LIBSTDCPP_GCC12_RANGE_ADAPTOR_CLOSURE && \
!BOOST_STL_INTERFACES_NEED_VS_COMPATIBLE_RANGE_ADAPTOR_CLOSURE
#define BOOST_STL_INTERFACES_DEFINE_CUSTOM_RANGE_ADAPTOR_CLOSURE 1
#else
#define BOOST_STL_INTERFACES_DEFINE_CUSTOM_RANGE_ADAPTOR_CLOSURE 0
#endif
#endif
namespace boost { namespace stl_interfaces {
namespace detail {
template<typename F, typename... Args>
using invocable_expr =
decltype(std::declval<F>()(std::declval<Args>()...));
template<typename F, typename... Args>
constexpr bool is_invocable_v =
is_detected_v<invocable_expr, F, Args...>;
template<typename Func, typename... CapturedArgs>
struct bind_back_t
{
static_assert(std::is_move_constructible<Func>::value, "");
#if defined(__cpp_fold_expressions)
static_assert(
(std::is_move_constructible<CapturedArgs>::value && ...), "");
#endif
template<typename F, typename... Args>
explicit constexpr bind_back_t(int, F && f, Args &&... args) :
f_((F &&) f), bound_args_((Args &&) args...)
{
static_assert(sizeof...(Args) == sizeof...(CapturedArgs), "");
}
template<typename... Args>
constexpr decltype(auto) operator()(Args &&... args) &
{
return call_impl(*this, indices(), (Args &&) args...);
}
template<typename... Args>
constexpr decltype(auto) operator()(Args &&... args) const &
{
return call_impl(*this, indices(), (Args &&) args...);
}
template<typename... Args>
constexpr decltype(auto) operator()(Args &&... args) &&
{
return call_impl(
std::move(*this), indices(), (Args &&) args...);
}
template<typename... Args>
constexpr decltype(auto) operator()(Args &&... args) const &&
{
return call_impl(
std::move(*this), indices(), (Args &&) args...);
}
private:
using indices = std::index_sequence_for<CapturedArgs...>;
template<typename T, size_t... I, typename... Args>
static constexpr decltype(auto)
call_impl(T && this_, std::index_sequence<I...>, Args &&... args)
{
return ((T &&) this_)
.f_((Args &&) args...,
std::get<I>(((T &&) this_).bound_args_)...);
}
Func f_;
std::tuple<CapturedArgs...> bound_args_;
};
template<typename Func, typename... Args>
using bind_back_result =
bind_back_t<std::decay_t<Func>, std::decay_t<Args>...>;
}
/** An implementation of `std::bind_back()` from C++23. */
template<typename Func, typename... Args>
constexpr auto bind_back(Func && f, Args &&... args)
{
return detail::bind_back_result<Func, Args...>(
0, (Func &&) f, (Args &&) args...);
}
#if BOOST_STL_INTERFACES_DEFINE_CUSTOM_RANGE_ADAPTOR_CLOSURE || \
defined(BOOST_STL_INTERFACES_DOXYGEN)
/** A backwards-compatible implementation of C++23's
`std::ranges::range_adaptor_closure`. `range_adaptor_closure` may be
a struct template or may be an alias, as required to maintain
compatability with the standard library's view adaptors. */
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<typename D>
requires std::is_class_v<D> && std::same_as<D, std::remove_cv_t<D>>
#else
template<
typename D,
typename Enable = std::enable_if_t<
std::is_class<D>::value &&
std::is_same<D, std::remove_cv_t<D>>::value>>
#endif
struct range_adaptor_closure;
namespace detail {
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<typename T>
concept range_adaptor_closure_ = std::derived_from<
std::remove_cvref_t<T>,
range_adaptor_closure<std::remove_cvref_t<T>>>;
#else
template<typename T>
using range_adaptor_closure_tag_expr = typename range_adaptor_closure<
T>::inheritance_tag_with_an_unlikely_name_;
template<typename T>
constexpr bool range_adaptor_closure_ =
is_detected_v<range_adaptor_closure_tag_expr, remove_cvref_t<T>>;
#endif
}
#endif
#if BOOST_STL_INTERFACES_USE_CPP23_STD_RANGE_ADAPTOR_CLOSURE
template<typename D>
using range_adaptor_closure = std::ranges::range_adaptor_closure<D>;
#elif BOOST_STL_INTERFACES_USE_LIBSTDCPP_GCC12_RANGE_ADAPTOR_CLOSURE
template<typename D>
using range_adaptor_closure = std::views::__adaptor::_RangeAdaptorClosure;
#elif BOOST_STL_INTERFACES_NEED_VS_COMPATIBLE_RANGE_ADAPTOR_CLOSURE
template<typename D>
using range_adaptor_closure = detail::pipeable<D>;
#else
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<typename D>
requires std::is_class_v<D> && std::same_as<D, std::remove_cv_t<D>>
#else
template<typename D, typename>
#endif
struct range_adaptor_closure
{
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<typename T>
requires std::invocable<D, T>
#else
template<
typename T,
typename Enable = std::enable_if_t<detail::is_invocable_v<D, T>>>
#endif
[[nodiscard]] friend constexpr decltype(auto) operator|(T && t, D && d)
{
return std::move(d)((T &&) t);
}
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<typename T>
requires std::invocable<D const &, T>
#else
template<
typename T,
typename Enable =
std::enable_if_t<detail::is_invocable_v<D const &, T>>>
#endif
[[nodiscard]] friend constexpr decltype(auto)
operator|(T && t, D const & d)
{
return d((T &&) t);
}
using inheritance_tag_with_an_unlikely_name_ = int;
};
#endif
//[closure_defn
/** An invocable consisting of a contained invocable `f`. Calling
`operator()` with some argument `t` calls `f(t)` and returns the
result. This type is typically used to capture a the result of a call
to `bind_back()`. */
template<typename F>
struct closure : range_adaptor_closure<closure<F>>
{
constexpr closure(F f) : f_(f) {}
#if BOOST_STL_INTERFACES_USE_CONCEPTS
template<typename T>
requires std::invocable<F const &, T>
#else
template<
typename T,
typename Enable =
std::enable_if_t<detail::is_invocable_v<F const &, T>>>
#endif
constexpr decltype(auto) operator()(T && t) const
{
return f_((T &&) t);
}
private:
F f_;
};
//]
namespace detail {
#if !BOOST_STL_INTERFACES_USE_CONCEPTS
template<typename F, bool Invocable, typename... Args>
struct adaptor_impl
{
static constexpr decltype(auto) call(F const & f, Args &&... args)
{
return f((Args &&) args...);
}
};
template<typename F, typename... Args>
struct adaptor_impl<F, false, Args...>
{
static constexpr auto call(F const & f, Args &&... args)
{
using closure_func =
std::decay_t<decltype(stl_interfaces::bind_back(
f, (Args &&) args...))>;
return closure<closure_func>(
stl_interfaces::bind_back(f, (Args &&) args...));
}
};
#endif
}
//[adaptor_defn
/** Adapts an invocable `f` as a view adaptor. Calling
`operator(args...)` will either: call `f(args...)` and return the
result, if `f(args...)` is well-formed; or return
`closure(stl_interfaces::bind_back(f, args...))` otherwise. */
template<typename F>
struct adaptor
{
constexpr adaptor(F f) : f_(f) {}
// clang-format off
template<typename... Args>
constexpr auto operator()(Args &&... args) const
// clang-format on
{
#if BOOST_STL_INTERFACES_USE_CONCEPTS
if constexpr (std::is_invocable_v<F const &, Args...>) {
return f((Args &&) args...);
} else {
return closure(
stl_interfaces::bind_back(f_, (Args &&) args...));
}
#else
return detail::adaptor_impl<
F const &,
detail::is_invocable_v<F const &, Args...>,
Args...>::call(f_, (Args &&) args...);
#endif
}
private:
F f_;
};
//]
}}
#endif

View File

@@ -0,0 +1,228 @@
// 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 { BOOST_STL_INTERFACES_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 defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 {
/** A template alias for `std::ranges::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, element_layout = element_layout::discontiguous>
using view_interface = std::ranges::view_interface<D>;
}}}
namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 {
/** A template alias for `std::ranges::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, element_layout = element_layout::discontiguous>
using view_interface = std::ranges::view_interface<D>;
}}}
#endif
#endif