@@ -0,0 +1,4 @@ | |||
Type: Library | |||
Name: ranges-v3 | |||
Include-Path: ranges-v3/include |
@@ -0,0 +1,6 @@ | |||
Type: Package | |||
Name: ranges-v3 | |||
Namespace: Niebler | |||
Library: ranges-v3.lml |
@@ -0,0 +1,326 @@ | |||
/// \file | |||
// Concepts library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
#ifndef CPP_SWAP_HPP | |||
#define CPP_SWAP_HPP | |||
#include <tuple> | |||
#include <utility> | |||
#include <type_traits> | |||
#include <meta/meta.hpp> | |||
// Note: constexpr implies inline, to retain the same visibility | |||
// C++14 constexpr functions are inline in C++11 | |||
#if (defined(__cpp_constexpr) && __cpp_constexpr >= 201304L) ||\ | |||
(!defined(__cpp_constexpr) && __cplusplus >= 201402L) | |||
#define CPP_CXX14_CONSTEXPR constexpr | |||
#else | |||
#define CPP_CXX14_CONSTEXPR inline | |||
#endif | |||
#ifndef CPP_CXX_INLINE_VARIABLES | |||
#ifdef __cpp_inline_variables // TODO: fix this if SD-6 picks another name | |||
#define CPP_CXX_INLINE_VARIABLES __cpp_inline_variables | |||
// TODO: remove once clang defines __cpp_inline_variables (or equivalent) | |||
#elif defined(__clang__) && \ | |||
(__clang_major__ > 3 || __clang_major__ == 3 && __clang_minor__ == 9) && \ | |||
__cplusplus > 201402L | |||
#define CPP_CXX_INLINE_VARIABLES 201606L | |||
#else | |||
#define CPP_CXX_INLINE_VARIABLES __cplusplus | |||
#endif // __cpp_inline_variables | |||
#endif // CPP_CXX_INLINE_VARIABLES | |||
#if defined(_MSC_VER) && !defined(__clang__) | |||
#define CPP_WORKAROUND_MSVC_895622 // Error when phase 1 name binding finds only deleted function | |||
#endif | |||
#if CPP_CXX_INLINE_VARIABLES < 201606L | |||
#define CPP_INLINE_VAR | |||
#define CPP_INLINE_VARIABLE(type, name) \ | |||
inline namespace \ | |||
{ \ | |||
constexpr auto &name = ::concepts::detail::static_const<type>::value; \ | |||
} \ | |||
/**/ | |||
#else // CPP_CXX_INLINE_VARIABLES >= 201606L | |||
#define CPP_INLINE_VAR inline | |||
#define CPP_INLINE_VARIABLE(type, name) \ | |||
inline constexpr type name{}; \ | |||
/**/ | |||
#endif // CPP_CXX_INLINE_VARIABLES | |||
#if CPP_CXX_INLINE_VARIABLES < 201606L | |||
#define CPP_DEFINE_CPO(type, name) \ | |||
inline namespace \ | |||
{ \ | |||
constexpr auto &name = ::concepts::detail::static_const<type>::value; \ | |||
} \ | |||
/**/ | |||
#else // CPP_CXX_INLINE_VARIABLES >= 201606L | |||
#define CPP_DEFINE_CPO(type, name) \ | |||
inline namespace _ \ | |||
{ \ | |||
inline constexpr type name{}; \ | |||
} \ | |||
/**/ | |||
#endif // CPP_CXX_INLINE_VARIABLES | |||
#if defined(_MSC_VER) && !defined(__clang__) | |||
#define CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME | |||
#else // ^^^ defined(_MSC_VER) ^^^ / vvv !defined(_MSC_VER) vvv | |||
#if defined(__GNUC__) || defined(__clang__) | |||
#define CPP_PRAGMA(X) _Pragma(#X) | |||
#define CPP_DIAGNOSTIC_IGNORE_PRAGMAS \ | |||
CPP_PRAGMA(GCC diagnostic ignored "-Wpragmas") | |||
#define CPP_DIAGNOSTIC_IGNORE(X) \ | |||
CPP_DIAGNOSTIC_IGNORE_PRAGMAS \ | |||
CPP_PRAGMA(GCC diagnostic ignored "-Wunknown-pragmas") \ | |||
CPP_PRAGMA(GCC diagnostic ignored X) | |||
#define CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME \ | |||
CPP_DIAGNOSTIC_IGNORE("-Wunknown-warning-option") \ | |||
CPP_DIAGNOSTIC_IGNORE("-Winit-list-lifetime") | |||
#else | |||
#define CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME | |||
#endif | |||
#endif // MSVC/Generic configuration switch | |||
namespace concepts | |||
{ | |||
/// \cond | |||
namespace detail | |||
{ | |||
template<typename T> | |||
CPP_INLINE_VAR constexpr bool is_movable_v = | |||
std::is_object<T>::value && | |||
std::is_move_constructible<T>::value && | |||
std::is_move_assignable<T>::value; | |||
template<typename T> | |||
struct static_const | |||
{ | |||
static constexpr T const value {}; | |||
}; | |||
template<typename T> | |||
constexpr T const static_const<T>::value; | |||
} | |||
/// \endcond | |||
template<typename T> | |||
struct is_swappable; | |||
template<typename T> | |||
struct is_nothrow_swappable; | |||
template<typename T, typename U> | |||
struct is_swappable_with; | |||
template<typename T, typename U> | |||
struct is_nothrow_swappable_with; | |||
template<typename T, typename U = T> | |||
CPP_CXX14_CONSTEXPR | |||
meta::if_c< | |||
std::is_move_constructible<T>::value && | |||
std::is_assignable<T &, U>::value, T> | |||
exchange(T &t, U &&u) | |||
noexcept( | |||
std::is_nothrow_move_constructible<T>::value && | |||
std::is_nothrow_assignable<T &, U>::value) | |||
{ | |||
T tmp((T &&) t); | |||
t = (U &&) u; | |||
CPP_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME | |||
return tmp; | |||
} | |||
/// \cond | |||
namespace adl_swap_detail | |||
{ | |||
struct nope | |||
{}; | |||
// Intentionally create an ambiguity with std::swap, which is | |||
// (possibly) unconstrained. | |||
template<typename T> | |||
nope swap(T &, T &) = delete; | |||
template<typename T, std::size_t N> | |||
nope swap(T (&)[N], T (&)[N]) = delete; | |||
#ifdef CPP_WORKAROUND_MSVC_895622 | |||
nope swap(); | |||
#endif | |||
template<typename T, typename U> | |||
decltype(swap(std::declval<T>(), std::declval<U>())) try_adl_swap_(int); | |||
template<typename T, typename U> | |||
nope try_adl_swap_(long); | |||
template<typename T, typename U = T> | |||
CPP_INLINE_VAR constexpr bool is_adl_swappable_v = | |||
!META_IS_SAME(decltype(adl_swap_detail::try_adl_swap_<T, U>(42)), nope); | |||
struct swap_fn | |||
{ | |||
// Dispatch to user-defined swap found via ADL: | |||
template<typename T, typename U> | |||
CPP_CXX14_CONSTEXPR | |||
meta::if_c<is_adl_swappable_v<T, U>> | |||
operator()(T &&t, U &&u) const | |||
noexcept(noexcept(swap((T &&) t, (U &&) u))) | |||
{ | |||
swap((T &&) t, (U &&) u); | |||
} | |||
// For intrinsically swappable (i.e., movable) types for which | |||
// a swap overload cannot be found via ADL, swap by moving. | |||
template<typename T> | |||
CPP_CXX14_CONSTEXPR | |||
meta::if_c< | |||
!is_adl_swappable_v<T &> && | |||
detail::is_movable_v<T>> | |||
operator()(T &a, T &b) const | |||
noexcept(noexcept(b = concepts::exchange(a, (T &&) b))) | |||
{ | |||
b = concepts::exchange(a, (T &&) b); | |||
} | |||
// For arrays of intrinsically swappable (i.e., movable) types | |||
// for which a swap overload cannot be found via ADL, swap array | |||
// elements by moving. | |||
template<typename T, typename U, std::size_t N> | |||
CPP_CXX14_CONSTEXPR | |||
meta::if_c< | |||
!is_adl_swappable_v<T (&)[N], U (&)[N]> && | |||
is_swappable_with<T &, U &>::value> | |||
operator()(T (&t)[N], U (&u)[N]) const | |||
noexcept(is_nothrow_swappable_with<T &, U &>::value) | |||
{ | |||
for(std::size_t i = 0; i < N; ++i) | |||
(*this)(t[i], u[i]); | |||
} | |||
// For rvalue pairs and tuples of swappable types, swap the | |||
// members. This permits code like: | |||
// ranges::swap(std::tie(a,b,c), std::tie(d,e,f)); | |||
template<typename F0, typename S0, typename F1, typename S1> | |||
CPP_CXX14_CONSTEXPR | |||
meta::if_c<is_swappable_with<F0, F1>::value && is_swappable_with<S0, S1>::value> | |||
operator()(std::pair<F0, S0> &&left, std::pair<F1, S1> &&right) const | |||
noexcept( | |||
is_nothrow_swappable_with<F0, F1>::value && | |||
is_nothrow_swappable_with<S0, S1>::value) | |||
{ | |||
swap_fn()(static_cast<std::pair<F0, S0> &&>(left).first, | |||
static_cast<std::pair<F1, S1> &&>(right).first); | |||
swap_fn()(static_cast<std::pair<F0, S0> &&>(left).second, | |||
static_cast<std::pair<F1, S1> &&>(right).second); | |||
} | |||
template<typename ...Ts, typename ...Us> | |||
CPP_CXX14_CONSTEXPR | |||
meta::if_c<meta::and_c<is_swappable_with<Ts, Us>::value...>::value> | |||
operator()(std::tuple<Ts...> &&left, std::tuple<Us...> &&right) const | |||
noexcept(meta::and_c<is_nothrow_swappable_with<Ts, Us>::value...>::value) | |||
{ | |||
swap_fn::impl( | |||
static_cast<std::tuple<Ts...> &&>(left), | |||
static_cast<std::tuple<Us...> &&>(right), | |||
meta::make_index_sequence<sizeof...(Ts)>{}); | |||
} | |||
private: | |||
template<typename... Ts> | |||
static constexpr int ignore_unused(Ts &&...) | |||
{ | |||
return 0; | |||
} | |||
template<typename T, typename U, std::size_t ...Is> | |||
CPP_CXX14_CONSTEXPR | |||
static void impl(T &&left, U &&right, meta::index_sequence<Is...>) | |||
{ | |||
(void) swap_fn::ignore_unused( | |||
(swap_fn()(std::get<Is>(static_cast<T &&>(left)), | |||
std::get<Is>(static_cast<U &&>(right))), 42)...); | |||
} | |||
}; | |||
template<typename T, typename U, typename = void> | |||
struct is_swappable_with_ | |||
: std::false_type | |||
{}; | |||
template<typename T, typename U> | |||
struct is_swappable_with_<T, U, meta::void_< | |||
decltype(swap_fn()(std::declval<T>(), std::declval<U>())), | |||
decltype(swap_fn()(std::declval<U>(), std::declval<T>()))>> | |||
: std::true_type | |||
{}; | |||
template<typename T, typename U> | |||
struct is_nothrow_swappable_with_ | |||
: meta::bool_<noexcept(swap_fn()(std::declval<T>(), std::declval<U>())) && | |||
noexcept(swap_fn()(std::declval<U>(), std::declval<T>()))> | |||
{}; | |||
// Q: Should std::reference_wrapper be considered a proxy wrt swapping rvalues? | |||
// A: No. Its operator= is currently defined to reseat the references, so | |||
// std::swap(ra, rb) already means something when ra and rb are (lvalue) | |||
// reference_wrappers. That reseats the reference wrappers but leaves the | |||
// referents unmodified. Treating rvalue reference_wrappers differently would | |||
// be confusing. | |||
// Q: Then why is it OK to "re"-define swap for pairs and tuples of references? | |||
// A: Because as defined above, swapping an rvalue tuple of references has the same | |||
// semantics as swapping an lvalue tuple of references. Rather than reseat the | |||
// references, assignment happens *through* the references. | |||
// Q: But I have an iterator whose operator* returns an rvalue | |||
// std::reference_wrapper<T>. How do I make it model indirectly_swappable? | |||
// A: With an overload of iter_swap. | |||
} | |||
/// \endcond | |||
/// \ingroup group-utility | |||
template<typename T, typename U> | |||
struct is_swappable_with | |||
: adl_swap_detail::is_swappable_with_<T, U> | |||
{}; | |||
/// \ingroup group-utility | |||
template<typename T, typename U> | |||
struct is_nothrow_swappable_with | |||
: meta::and_< | |||
is_swappable_with<T, U>, | |||
adl_swap_detail::is_nothrow_swappable_with_<T, U>> | |||
{}; | |||
/// \ingroup group-utility | |||
template<typename T> | |||
struct is_swappable | |||
: is_swappable_with<T &, T &> | |||
{}; | |||
/// \ingroup group-utility | |||
template<typename T> | |||
struct is_nothrow_swappable | |||
: is_nothrow_swappable_with<T &, T &> | |||
{}; | |||
/// \ingroup group-utility | |||
/// \relates adl_swap_detail::swap_fn | |||
CPP_DEFINE_CPO(adl_swap_detail::swap_fn, swap) | |||
} | |||
#endif |
@@ -0,0 +1,363 @@ | |||
/// \file | |||
// Concepts library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
#ifndef CPP_TYPE_TRAITS_HPP | |||
#define CPP_TYPE_TRAITS_HPP | |||
#include <tuple> | |||
#include <utility> | |||
#include <type_traits> | |||
#include <meta/meta.hpp> | |||
namespace concepts | |||
{ | |||
template<typename T> | |||
using remove_cvref_t = | |||
typename std::remove_cv< | |||
typename std::remove_reference<T>::type>::type; | |||
/// \cond | |||
namespace detail | |||
{ | |||
template<typename From, typename To> | |||
using is_convertible = std::is_convertible<meta::_t<std::add_rvalue_reference<From>>, To>; | |||
template<bool> | |||
struct if_else_ | |||
{ | |||
template<typename, typename U> | |||
using invoke = U; | |||
}; | |||
template<> | |||
struct if_else_<true> | |||
{ | |||
template<typename T, typename> | |||
using invoke = T; | |||
}; | |||
template<bool B, typename T, typename U> | |||
using if_else_t = meta::invoke<if_else_<B>, T, U>; | |||
template<bool> | |||
struct if_ | |||
{}; | |||
template<> | |||
struct if_<true> | |||
{ | |||
template<typename T> | |||
using invoke = T; | |||
}; | |||
template<bool B, typename T = void> | |||
using if_t = meta::invoke<if_<B>, T>; | |||
template<typename From, typename To> | |||
struct _copy_cv_ | |||
{ | |||
using type = To; | |||
}; | |||
template<typename From, typename To> | |||
struct _copy_cv_<From const, To> | |||
{ | |||
using type = To const; | |||
}; | |||
template<typename From, typename To> | |||
struct _copy_cv_<From volatile, To> | |||
{ | |||
using type = To volatile; | |||
}; | |||
template<typename From, typename To> | |||
struct _copy_cv_<From const volatile, To> | |||
{ | |||
using type = To const volatile; | |||
}; | |||
template<typename From, typename To> | |||
using _copy_cv = meta::_t<_copy_cv_<From, To>>; | |||
//////////////////////////////////////////////////////////////////////////////////////// | |||
template<typename T, typename U, typename = void> | |||
struct _builtin_common; | |||
template<typename T, typename U> | |||
using _builtin_common_t = meta::_t<_builtin_common<T, U>>; | |||
template<typename T, typename U> | |||
using _cond_res = decltype(true ? std::declval<T>() : std::declval<U>()); | |||
template<typename T, typename U, typename R = _builtin_common_t<T &, U &>> | |||
using _rref_res = | |||
if_else_t<std::is_reference<R>::value, meta::_t<std::remove_reference<R>> &&, R>; | |||
template<typename T, typename U> | |||
using _lref_res = _cond_res<_copy_cv<T, U> &, _copy_cv<U, T> &>; | |||
template<typename T> | |||
struct as_cref_ | |||
{ | |||
using type = T const &; | |||
}; | |||
template<typename T> | |||
struct as_cref_<T &> | |||
{ | |||
using type = T const &; | |||
}; | |||
template<typename T> | |||
struct as_cref_<T &&> | |||
{ | |||
using type = T const &; | |||
}; | |||
template<> | |||
struct as_cref_<void> | |||
{ | |||
using type = void; | |||
}; | |||
template<> | |||
struct as_cref_<void const> | |||
{ | |||
using type = void const; | |||
}; | |||
template<typename T> | |||
using as_cref_t = typename as_cref_<T>::type; | |||
template<typename T> | |||
using decay_t = typename std::decay<T>::type; | |||
#if !defined(__GNUC__) || defined(__clang__) | |||
template<typename T, typename U, typename = void> | |||
struct _builtin_common_2 | |||
{}; | |||
template<typename T, typename U> | |||
struct _builtin_common_2<T, U, meta::void_<_cond_res<as_cref_t<T>, as_cref_t<U>>>> | |||
: std::decay<_cond_res<as_cref_t<T>, as_cref_t<U>>> | |||
{}; | |||
template<typename T, typename U, typename /* = void */> | |||
struct _builtin_common | |||
: _builtin_common_2<T, U> | |||
{}; | |||
template<typename T, typename U> | |||
struct _builtin_common<T &&, U &&, if_t< | |||
is_convertible<T &&, _rref_res<T, U>>::value && | |||
is_convertible<U &&, _rref_res<T, U>>::value>> | |||
{ | |||
using type = _rref_res<T, U>; | |||
}; | |||
template<typename T, typename U> | |||
struct _builtin_common<T &, U &> | |||
: meta::defer<_lref_res, T, U> | |||
{}; | |||
template<typename T, typename U> | |||
struct _builtin_common<T &, U &&, if_t< | |||
is_convertible<U &&, _builtin_common_t<T &, U const &>>::value>> | |||
: _builtin_common<T &, U const &> | |||
{}; | |||
template<typename T, typename U> | |||
struct _builtin_common<T &&, U &> | |||
: _builtin_common<U &, T &&> | |||
{}; | |||
#else | |||
template<typename T, typename U, typename = void> | |||
struct _builtin_common_ | |||
{}; | |||
template<typename T, typename U> | |||
struct _builtin_common_<T, U, meta::void_<_cond_res<as_cref_t<T>, as_cref_t<U>>>> | |||
: std::decay<_cond_res<as_cref_t<T>, as_cref_t<U>>> | |||
{}; | |||
template<typename T, typename U, typename /* = void */> | |||
struct _builtin_common | |||
: _builtin_common_<T, U> | |||
{}; | |||
template<typename T, typename U, typename = void> | |||
struct _builtin_common_rr | |||
: _builtin_common_<T &&, U &&> | |||
{}; | |||
template<typename T, typename U> | |||
struct _builtin_common_rr<T, U, if_t< | |||
is_convertible<T &&, _rref_res<T, U>>::value && | |||
is_convertible<U &&, _rref_res<T, U>>::value>> | |||
{ | |||
using type = _rref_res<T, U>; | |||
}; | |||
template<typename T, typename U> | |||
struct _builtin_common<T &&, U &&> | |||
: _builtin_common_rr<T, U> | |||
{}; | |||
template<typename T, typename U> | |||
struct _builtin_common<T &, U &> | |||
: meta::defer<_lref_res, T, U> | |||
{}; | |||
template<typename T, typename U, typename = void> | |||
struct _builtin_common_lr | |||
: _builtin_common_<T &, T &&> | |||
{}; | |||
template<typename T, typename U> | |||
struct _builtin_common_lr<T, U, if_t< | |||
is_convertible<U &&, _builtin_common_t<T &, U const &>>::value>> | |||
: _builtin_common<T &, U const &> | |||
{}; | |||
template<typename T, typename U> | |||
struct _builtin_common<T &, U &&> | |||
: _builtin_common_lr<T, U> | |||
{}; | |||
template<typename T, typename U> | |||
struct _builtin_common<T &&, U &> | |||
: _builtin_common<U &, T &&> | |||
{}; | |||
#endif | |||
} | |||
/// \endcond | |||
/// \addtogroup group-utility Utility | |||
/// @{ | |||
/// | |||
/// Users should specialize this to hook the \c common_with concept | |||
/// until \c std gets a SFINAE-friendly \c std::common_type and there's | |||
/// some sane way to deal with cv and ref qualifiers. | |||
template<typename ...Ts> | |||
struct common_type | |||
{}; | |||
template<typename T> | |||
struct common_type<T> | |||
: std::decay<T> | |||
{}; | |||
template<typename T, typename U> | |||
struct common_type<T, U> | |||
: detail::if_else_t< | |||
(META_IS_SAME(detail::decay_t<T>, T) && | |||
META_IS_SAME(detail::decay_t<U>, U) ), | |||
meta::defer<detail::_builtin_common_t, T, U>, | |||
common_type<detail::decay_t<T>, detail::decay_t<U>>> | |||
{}; | |||
template<typename... Ts> | |||
using common_type_t = typename common_type<Ts...>::type; | |||
template<typename T, typename U, typename... Vs> | |||
struct common_type<T, U, Vs...> | |||
: meta::lazy::fold<meta::list<U, Vs...>, T, meta::quote<common_type_t>> | |||
{}; | |||
/// @} | |||
/// \addtogroup group-utility Utility | |||
/// @{ | |||
/// | |||
/// Users can specialize this to hook the \c common_reference_with concept. | |||
/// \sa `common_reference` | |||
template< | |||
typename T, | |||
typename U, | |||
template<typename> class TQual, | |||
template<typename> class UQual> | |||
struct basic_common_reference | |||
{}; | |||
/// \cond | |||
namespace detail | |||
{ | |||
using _rref = | |||
meta::quote_trait<std::add_rvalue_reference>; | |||
using _lref = | |||
meta::quote_trait<std::add_lvalue_reference>; | |||
template<typename> | |||
struct _xref | |||
{ | |||
template<typename T> | |||
using invoke = T; | |||
}; | |||
template<typename T> | |||
struct _xref<T &&> | |||
{ | |||
template<typename U> | |||
using invoke = | |||
meta::_t<std::add_rvalue_reference<meta::invoke<_xref<T>, U>>>; | |||
}; | |||
template<typename T> | |||
struct _xref<T &> | |||
{ | |||
template<typename U> | |||
using invoke = | |||
meta::_t<std::add_lvalue_reference<meta::invoke<_xref<T>, U>>>; | |||
}; | |||
template<typename T> | |||
struct _xref<T const> | |||
{ | |||
template<typename U> | |||
using invoke = U const; | |||
}; | |||
template<typename T> | |||
struct _xref<T volatile> | |||
{ | |||
template<typename U> | |||
using invoke = U volatile; | |||
}; | |||
template<typename T> | |||
struct _xref<T const volatile> | |||
{ | |||
template<typename U> | |||
using invoke = U const volatile; | |||
}; | |||
template<typename T, typename U> | |||
using _basic_common_reference = | |||
basic_common_reference< | |||
remove_cvref_t<T>, | |||
remove_cvref_t<U>, | |||
_xref<T>::template invoke, | |||
_xref<U>::template invoke>; | |||
template<typename T, typename U, typename = void> | |||
struct _common_reference2 | |||
: if_else_t< | |||
meta::is_trait<_basic_common_reference<T, U>>::value, | |||
_basic_common_reference<T, U>, | |||
common_type<T, U>> | |||
{}; | |||
template<typename T, typename U> | |||
struct _common_reference2<T, U, if_t<std::is_reference<_builtin_common_t<T, U>>::value>> | |||
: _builtin_common<T, U> | |||
{}; | |||
} | |||
/// \endcond | |||
/// Users can specialize this to hook the \c common_reference_with concept. | |||
/// \sa `basic_common_reference` | |||
template<typename ...Ts> | |||
struct common_reference | |||
{}; | |||
template<typename T> | |||
struct common_reference<T> | |||
{ | |||
using type = T; | |||
}; | |||
template<typename T, typename U> | |||
struct common_reference<T, U> | |||
: detail::_common_reference2<T, U> | |||
{}; | |||
template<typename... Ts> | |||
using common_reference_t = typename common_reference<Ts...>::type; | |||
template<typename T, typename U, typename... Vs> | |||
struct common_reference<T, U, Vs...> | |||
: meta::lazy::fold<meta::list<U, Vs...>, T, meta::quote<common_reference_t>> | |||
{}; | |||
/// @} | |||
} // namespace concepts | |||
#endif |
@@ -0,0 +1,359 @@ | |||
/// \file meta_fwd.hpp Forward declarations | |||
// | |||
// Meta library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/meta | |||
// | |||
#ifndef META_FWD_HPP | |||
#define META_FWD_HPP | |||
#include <type_traits> | |||
#include <utility> | |||
#ifdef __clang__ | |||
#pragma GCC diagnostic push | |||
#pragma GCC diagnostic ignored "-Wmissing-variable-declarations" | |||
#endif | |||
#define META_CXX_STD_14 201402L | |||
#define META_CXX_STD_17 201703L | |||
#if defined(_MSVC_LANG) && _MSVC_LANG > __cplusplus // Older clangs define _MSVC_LANG < __cplusplus | |||
#define META_CXX_VER _MSVC_LANG | |||
#else | |||
#define META_CXX_VER __cplusplus | |||
#endif | |||
#if defined(__apple_build_version__) || defined(__clang__) | |||
#if defined(__apple_build_version__) || (defined(__clang__) && __clang_major__ < 6) | |||
#define META_WORKAROUND_LLVM_28385 // https://llvm.org/bugs/show_bug.cgi?id=28385 | |||
#endif | |||
#elif defined(_MSC_VER) | |||
#define META_HAS_MAKE_INTEGER_SEQ 1 | |||
#if _MSC_VER < 1920 | |||
#define META_WORKAROUND_MSVC_702792 // Bogus C4018 comparing constant expressions with dependent type | |||
#define META_WORKAROUND_MSVC_703656 // ICE with pack expansion inside decltype in alias template | |||
#endif | |||
#if _MSC_VER < 1921 | |||
#define META_WORKAROUND_MSVC_756112 // fold expression + alias templates in template argument | |||
#endif | |||
#elif defined(__GNUC__) | |||
#define META_WORKAROUND_GCC_86356 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86356 | |||
#if __GNUC__ < 8 | |||
#define META_WORKAROUND_GCC_UNKNOWN1 // Older GCCs don't like fold + debug + -march=native | |||
#endif | |||
#if __GNUC__ == 5 && __GNUC_MINOR__ == 1 | |||
#define META_WORKAROUND_GCC_66405 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66405 | |||
#endif | |||
#if __GNUC__ < 5 | |||
#define META_WORKAROUND_CWG_1558 // https://wg21.link/cwg1558 | |||
#endif | |||
#endif | |||
#ifndef META_CXX_VARIABLE_TEMPLATES | |||
#ifdef __cpp_variable_templates | |||
#define META_CXX_VARIABLE_TEMPLATES __cpp_variable_templates | |||
#else | |||
#define META_CXX_VARIABLE_TEMPLATES (META_CXX_VER >= META_CXX_STD_14) | |||
#endif | |||
#endif | |||
#ifndef META_CXX_INLINE_VARIABLES | |||
#ifdef __cpp_inline_variables | |||
#define META_CXX_INLINE_VARIABLES __cpp_inline_variables | |||
#else | |||
#define META_CXX_INLINE_VARIABLES (META_CXX_VER >= META_CXX_STD_17) | |||
#endif | |||
#endif | |||
#ifndef META_INLINE_VAR | |||
#if META_CXX_INLINE_VARIABLES | |||
#define META_INLINE_VAR inline | |||
#else | |||
#define META_INLINE_VAR | |||
#endif | |||
#endif | |||
#ifndef META_CXX_INTEGER_SEQUENCE | |||
#ifdef __cpp_lib_integer_sequence | |||
#define META_CXX_INTEGER_SEQUENCE __cpp_lib_integer_sequence | |||
#else | |||
#define META_CXX_INTEGER_SEQUENCE (META_CXX_VER >= META_CXX_STD_14) | |||
#endif | |||
#endif | |||
#ifndef META_HAS_MAKE_INTEGER_SEQ | |||
#ifdef __has_builtin | |||
#if __has_builtin(__make_integer_seq) | |||
#define META_HAS_MAKE_INTEGER_SEQ 1 | |||
#endif | |||
#endif | |||
#endif | |||
#ifndef META_HAS_MAKE_INTEGER_SEQ | |||
#define META_HAS_MAKE_INTEGER_SEQ 0 | |||
#endif | |||
#ifndef META_HAS_TYPE_PACK_ELEMENT | |||
#ifdef __has_builtin | |||
#if __has_builtin(__type_pack_element) | |||
#define META_HAS_TYPE_PACK_ELEMENT 1 | |||
#endif | |||
#endif | |||
#endif | |||
#ifndef META_HAS_TYPE_PACK_ELEMENT | |||
#define META_HAS_TYPE_PACK_ELEMENT 0 | |||
#endif | |||
#if !defined(META_DEPRECATED) && !defined(META_DISABLE_DEPRECATED_WARNINGS) | |||
#if defined(__cpp_attribute_deprecated) || META_CXX_VER >= META_CXX_STD_14 | |||
#define META_DEPRECATED(...) [[deprecated(__VA_ARGS__)]] | |||
#elif defined(__clang__) || defined(__GNUC__) | |||
#define META_DEPRECATED(...) __attribute__((deprecated(__VA_ARGS__))) | |||
#endif | |||
#endif | |||
#ifndef META_DEPRECATED | |||
#define META_DEPRECATED(...) | |||
#endif | |||
#ifndef META_CXX_FOLD_EXPRESSIONS | |||
#ifdef __cpp_fold_expressions | |||
#define META_CXX_FOLD_EXPRESSIONS __cpp_fold_expressions | |||
#else | |||
#define META_CXX_FOLD_EXPRESSIONS (META_CXX_VER >= META_CXX_STD_17) | |||
#endif | |||
#endif | |||
#if META_CXX_FOLD_EXPRESSIONS | |||
#if !META_CXX_VARIABLE_TEMPLATES | |||
#error Fold expressions, but no variable templates? | |||
#endif | |||
#endif | |||
#if defined(__cpp_concepts) && __cpp_concepts > 0 | |||
#if !META_CXX_VARIABLE_TEMPLATES | |||
#error Concepts, but no variable templates? | |||
#endif | |||
#if __cpp_concepts <= 201507L | |||
#define META_CONCEPT concept bool | |||
// TS concepts subsumption barrier for atomic expressions | |||
#define META_CONCEPT_BARRIER(...) ::meta::detail::barrier<__VA_ARGS__> | |||
#else | |||
#define META_CONCEPT concept | |||
#define META_CONCEPT_BARRIER(...) __VA_ARGS__ | |||
#endif | |||
#define META_TYPE_CONSTRAINT(...) __VA_ARGS__ | |||
#else | |||
#define META_TYPE_CONSTRAINT(...) typename | |||
#endif | |||
#if (defined(__cpp_lib_type_trait_variable_templates) && \ | |||
__cpp_lib_type_trait_variable_templates > 0) | |||
#define META_CXX_TRAIT_VARIABLE_TEMPLATES 1 | |||
#else | |||
#define META_CXX_TRAIT_VARIABLE_TEMPLATES 0 | |||
#endif | |||
#if defined(__clang__) | |||
#define META_IS_SAME(...) __is_same(__VA_ARGS__) | |||
#elif defined(__GNUC__) && __GNUC__ >= 6 | |||
#define META_IS_SAME(...) __is_same_as(__VA_ARGS__) | |||
#elif META_CXX_TRAIT_VARIABLE_TEMPLATES | |||
#define META_IS_SAME(...) std::is_same_v<__VA_ARGS__> | |||
#else | |||
#define META_IS_SAME(...) std::is_same<__VA_ARGS__>::value | |||
#endif | |||
#if defined(__GNUC__) || defined(_MSC_VER) | |||
#define META_IS_BASE_OF(...) __is_base_of(__VA_ARGS__) | |||
#elif META_CXX_TRAIT_VARIABLE_TEMPLATES | |||
#define META_IS_BASE_OF(...) std::is_base_of_v<__VA_ARGS__> | |||
#else | |||
#define META_IS_BASE_OF(...) std::is_base_of<__VA_ARGS__>::value | |||
#endif | |||
#if defined(__clang__) || defined(_MSC_VER) || \ | |||
(defined(__GNUC__) && __GNUC__ >= 8) | |||
#define META_IS_CONSTRUCTIBLE(...) __is_constructible(__VA_ARGS__) | |||
#elif META_CXX_TRAIT_VARIABLE_TEMPLATES | |||
#define META_IS_CONSTRUCTIBLE(...) std::is_constructible_v<__VA_ARGS__> | |||
#else | |||
#define META_IS_CONSTRUCTIBLE(...) std::is_constructible<__VA_ARGS__>::value | |||
#endif | |||
/// \cond | |||
// Non-portable forward declarations of standard containers | |||
#ifdef _LIBCPP_VERSION | |||
#define META_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD | |||
#define META_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD | |||
#elif defined(_MSVC_STL_VERSION) | |||
#define META_BEGIN_NAMESPACE_STD _STD_BEGIN | |||
#define META_END_NAMESPACE_STD _STD_END | |||
#else | |||
#define META_BEGIN_NAMESPACE_STD namespace std { | |||
#define META_END_NAMESPACE_STD } | |||
#endif | |||
#if defined(__GLIBCXX__) | |||
#define META_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION | |||
#define META_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION | |||
#define META_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_BEGIN_NAMESPACE_CONTAINER | |||
#define META_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER | |||
#else | |||
#define META_BEGIN_NAMESPACE_VERSION | |||
#define META_END_NAMESPACE_VERSION | |||
#define META_BEGIN_NAMESPACE_CONTAINER | |||
#define META_END_NAMESPACE_CONTAINER | |||
#endif | |||
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 4000 | |||
#define META_TEMPLATE_VIS _LIBCPP_TEMPLATE_VIS | |||
#elif defined(_LIBCPP_VERSION) | |||
#define META_TEMPLATE_VIS _LIBCPP_TYPE_VIS_ONLY | |||
#else | |||
#define META_TEMPLATE_VIS | |||
#endif | |||
/// \endcond | |||
namespace meta | |||
{ | |||
#if META_CXX_INTEGER_SEQUENCE | |||
using std::integer_sequence; | |||
#else | |||
template <typename T, T...> | |||
struct integer_sequence; | |||
#endif | |||
template <typename... Ts> | |||
struct list; | |||
template <typename T> | |||
struct id; | |||
template <template <typename...> class> | |||
struct quote; | |||
template <typename T, template <T...> class F> | |||
struct quote_i; | |||
template <template <typename...> class C, typename... Ts> | |||
struct defer; | |||
template <typename T, template <T...> class C, T... Is> | |||
struct defer_i; | |||
#if META_CXX_VARIABLE_TEMPLATES || defined(META_DOXYGEN_INVOKED) | |||
/// is_v | |||
/// Test whether a type \p T is an instantiation of class | |||
/// template \p C. | |||
/// \ingroup trait | |||
template <typename, template <typename...> class> | |||
META_INLINE_VAR constexpr bool is_v = false; | |||
template <typename... Ts, template <typename...> class C> | |||
META_INLINE_VAR constexpr bool is_v<C<Ts...>, C> = true; | |||
#endif | |||
#ifdef META_CONCEPT | |||
namespace detail | |||
{ | |||
template <bool B> | |||
META_INLINE_VAR constexpr bool barrier = B; | |||
template <class T, T> struct require_constant; // not defined | |||
} | |||
template <typename...> | |||
META_CONCEPT is_true = META_CONCEPT_BARRIER(true); | |||
template <typename T, typename U> | |||
META_CONCEPT same_as = | |||
META_CONCEPT_BARRIER(META_IS_SAME(T, U)); | |||
template <template <typename...> class C, typename... Ts> | |||
META_CONCEPT valid = requires | |||
{ | |||
typename C<Ts...>; | |||
}; | |||
template <typename T, template <T...> class C, T... Is> | |||
META_CONCEPT valid_i = requires | |||
{ | |||
typename C<Is...>; | |||
}; | |||
template <typename T> | |||
META_CONCEPT trait = requires | |||
{ | |||
typename T::type; | |||
}; | |||
template <typename T> | |||
META_CONCEPT invocable = requires | |||
{ | |||
typename quote<T::template invoke>; | |||
}; | |||
template <typename T> | |||
META_CONCEPT list_like = is_v<T, list>; | |||
// clang-format off | |||
template <typename T> | |||
META_CONCEPT integral = requires | |||
{ | |||
typename T::type; | |||
typename T::value_type; | |||
typename T::type::value_type; | |||
} | |||
&& same_as<typename T::value_type, typename T::type::value_type> | |||
#if META_CXX_TRAIT_VARIABLE_TEMPLATES | |||
&& std::is_integral_v<typename T::value_type> | |||
#else | |||
&& std::is_integral<typename T::value_type>::value | |||
#endif | |||
&& requires | |||
{ | |||
// { T::value } -> same_as<const typename T::value_type&>; | |||
T::value; | |||
requires same_as<decltype(T::value), const typename T::value_type>; | |||
typename detail::require_constant<decltype(T::value), T::value>; | |||
// { T::type::value } -> same_as<const typename T::value_type&>; | |||
T::type::value; | |||
requires same_as<decltype(T::type::value), const typename T::value_type>; | |||
typename detail::require_constant<decltype(T::type::value), T::type::value>; | |||
requires T::value == T::type::value; | |||
// { T{}() } -> same_as<typename T::value_type>; | |||
T{}(); | |||
requires same_as<decltype(T{}()), typename T::value_type>; | |||
typename detail::require_constant<decltype(T{}()), T{}()>; | |||
requires T{}() == T::value; | |||
{ T{} } -> typename T::value_type; | |||
}; | |||
// clang-format on | |||
#endif // META_CONCEPT | |||
namespace extension | |||
{ | |||
template <META_TYPE_CONSTRAINT(invocable) F, typename L> | |||
struct apply; | |||
} | |||
} // namespace meta | |||
#ifdef __clang__ | |||
#pragma GCC diagnostic pop | |||
#endif | |||
#endif |
@@ -0,0 +1,61 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Gonzalo Brito Gadeschi 2017. | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
module concepts { | |||
umbrella "concepts" | |||
export * | |||
} | |||
module meta { | |||
umbrella "meta" | |||
export * | |||
} | |||
module range_v3 { | |||
umbrella "range" | |||
export * | |||
exclude header "range/v3/algorithm/tagspec.hpp" | |||
exclude header "range/v3/at.hpp" | |||
exclude header "range/v3/back.hpp" | |||
exclude header "range/v3/begin_end.hpp" | |||
exclude header "range/v3/data.hpp" | |||
exclude header "range/v3/distance.hpp" | |||
exclude header "range/v3/empty.hpp" | |||
exclude header "range/v3/front.hpp" | |||
exclude header "range/v3/getlines.hpp" | |||
exclude header "range/v3/index.hpp" | |||
exclude header "range/v3/istream_range.hpp" | |||
exclude header "range/v3/iterator_range.hpp" | |||
exclude header "range/v3/range_access.hpp" | |||
exclude header "range/v3/range_concepts.hpp" | |||
exclude header "range/v3/range_traits.hpp" | |||
exclude header "range/v3/size.hpp" | |||
exclude header "range/v3/span.hpp" | |||
exclude header "range/v3/to_container.hpp" | |||
exclude header "range/v3/utility/associated_types.hpp" | |||
exclude header "range/v3/utility/basic_iterator.hpp" | |||
exclude header "range/v3/utility/common_iterator.hpp" | |||
exclude header "range/v3/utility/concepts.hpp" | |||
exclude header "range/v3/utility/counted_iterator.hpp" | |||
exclude header "range/v3/utility/dangling.hpp" | |||
exclude header "range/v3/utility/functional.hpp" | |||
exclude header "range/v3/utility/infinity.hpp" | |||
exclude header "range/v3/utility/invoke.hpp" | |||
exclude header "range/v3/utility/iterator_concepts.hpp" | |||
exclude header "range/v3/utility/iterator_traits.hpp" | |||
exclude header "range/v3/utility/iterator.hpp" | |||
exclude header "range/v3/utility/nullptr_v.hpp" | |||
exclude header "range/v3/utility/unreachable.hpp" | |||
exclude header "range/v3/view_adaptor.hpp" | |||
exclude header "range/v3/view_facade.hpp" | |||
exclude header "range/v3/view_interface.hpp" | |||
exclude header "range/v3/view/bounded.hpp" | |||
} |
@@ -0,0 +1,42 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_HPP | |||
#define RANGES_V3_ACTION_HPP | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/adjacent_remove_if.hpp> | |||
#include <range/v3/action/concepts.hpp> | |||
#include <range/v3/action/drop.hpp> | |||
#include <range/v3/action/drop_while.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/action/insert.hpp> | |||
#include <range/v3/action/join.hpp> | |||
#include <range/v3/action/push_back.hpp> | |||
#include <range/v3/action/push_front.hpp> | |||
#include <range/v3/action/remove_if.hpp> | |||
#include <range/v3/action/reverse.hpp> | |||
#include <range/v3/action/shuffle.hpp> | |||
#include <range/v3/action/slice.hpp> | |||
#include <range/v3/action/sort.hpp> | |||
#include <range/v3/action/split.hpp> | |||
#include <range/v3/action/split_when.hpp> | |||
#include <range/v3/action/stable_sort.hpp> | |||
#include <range/v3/action/stride.hpp> | |||
#include <range/v3/action/take.hpp> | |||
#include <range/v3/action/take_while.hpp> | |||
#include <range/v3/action/transform.hpp> | |||
#include <range/v3/action/unique.hpp> | |||
#include <range/v3/action/unstable_remove_if.hpp> | |||
#endif |
@@ -0,0 +1,125 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_CONTAINER_ACTION_HPP | |||
#define RANGES_V3_CONTAINER_ACTION_HPP | |||
#include <type_traits> | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/concepts.hpp> | |||
#include <range/v3/functional/arithmetic.hpp> | |||
#include <range/v3/functional/concepts.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
#include <range/v3/view/ref.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct action_access | |||
{ | |||
template<typename Action> | |||
struct impl | |||
{ | |||
// clang-format off | |||
template<typename... Ts, typename A = Action> | |||
static constexpr auto CPP_auto_fun(bind)(Ts &&... ts) | |||
( | |||
return A::bind(static_cast<Ts &&>(ts)...) | |||
) | |||
// clang-format on | |||
}; | |||
}; | |||
struct make_action_fn | |||
{ | |||
template<typename Fun> | |||
constexpr action<Fun> operator()(Fun fun) const | |||
{ | |||
return action<Fun>{detail::move(fun)}; | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates make_action_fn | |||
RANGES_INLINE_VARIABLE(make_action_fn, make_action) | |||
template<typename Action> | |||
struct action : pipeable_base | |||
{ | |||
private: | |||
Action action_; | |||
friend pipeable_access; | |||
// Piping requires things are passed by value. | |||
template<typename Rng, typename Act> | |||
static auto pipe(Rng && rng, Act && act) | |||
-> CPP_ret(invoke_result_t<Action &, Rng>)( // | |||
requires range<Rng> && invocable<Action &, Rng> && | |||
(!std::is_reference<Rng>::value)) | |||
{ | |||
return invoke(act.action_, detail::move(rng)); | |||
} | |||
public: | |||
action() = default; | |||
constexpr explicit action(Action a) noexcept( | |||
std::is_nothrow_move_constructible<Action>::value) | |||
: action_(detail::move(a)) | |||
{} | |||
// Calling directly requires things are passed by reference. | |||
template<typename Rng, typename... Rest> | |||
auto operator()(Rng & rng, Rest &&... rest) const | |||
-> CPP_ret(invoke_result_t<Action const &, Rng &, Rest...>)( // | |||
requires range<Rng> && invocable<Action const &, Rng &, Rest...>) | |||
{ | |||
return invoke(action_, rng, static_cast<Rest &&>(rest)...); | |||
} | |||
// Currying overload. | |||
// clang-format off | |||
template<typename T, typename... Rest, typename A = Action> | |||
auto CPP_auto_fun(operator())(T &&t, Rest &&... rest)(const) | |||
( | |||
return make_action( | |||
action_access::impl<A>::bind(action_, | |||
static_cast<T &&>(t), | |||
static_cast<Rest &&>(rest)...)) | |||
) | |||
// clang-format on | |||
}; | |||
template<typename Rng, typename Action> | |||
auto operator|=(Rng & rng, Action && action) -> CPP_ret(Rng &)( // | |||
requires is_pipeable<Action>::value && range<Rng &> && | |||
invocable<bitwise_or, ref_view<Rng>, Action &> && same_as< | |||
ref_view<Rng>, invoke_result_t<bitwise_or, ref_view<Rng>, Action &>>) | |||
{ | |||
views::ref(rng) | action; | |||
return rng; | |||
} | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,70 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler | |||
// Copyright Christopher Di Bella | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_ADJACENT_REMOVE_IF_HPP | |||
#define RANGES_V3_ACTION_ADJACENT_REMOVE_IF_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/algorithm/adjacent_remove_if.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct adjacent_remove_if_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename Pred, typename Proj = identity> | |||
static auto CPP_fun(bind)(adjacent_remove_if_fn adjacent_remove_if, Pred pred, | |||
Proj proj = {})( // | |||
requires(!range<Pred>)) | |||
{ | |||
return bind_back(adjacent_remove_if, std::move(pred), std::move(proj)); | |||
} | |||
public: | |||
template<typename Rng, typename Pred, typename Proj = identity> | |||
auto operator()(Rng && rng, Pred pred, Proj proj = {}) const | |||
-> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && | |||
erasable_range<Rng, iterator_t<Rng>, sentinel_t<Rng>> && | |||
indirect_relation<Pred, projected<iterator_t<Rng>, Proj>> && | |||
permutable<iterator_t<Rng>>) | |||
{ | |||
auto i = adjacent_remove_if(rng, std::move(pred), std::move(proj)); | |||
erase(rng, std::move(i), end(rng)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \sa action | |||
/// \sa with_braced_init_args | |||
RANGES_INLINE_VARIABLE(action<adjacent_remove_if_fn>, adjacent_remove_if) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif // RANGES_V3_ACTION_ADJACENT_REMOVE_IF_HPP |
@@ -0,0 +1,163 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_CONCEPTS_HPP | |||
#define RANGES_V3_ACTION_CONCEPTS_HPP | |||
#include <utility> | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
namespace ranges | |||
{ | |||
/// \cond | |||
namespace detail | |||
{ | |||
template<typename T> | |||
struct movable_input_iterator | |||
{ | |||
using iterator_category = std::input_iterator_tag; | |||
using value_type = T; | |||
using difference_type = std::ptrdiff_t; | |||
using pointer = T *; | |||
using reference = T &&; | |||
movable_input_iterator() = default; | |||
movable_input_iterator & operator++(); | |||
movable_input_iterator operator++(int); | |||
bool operator==(movable_input_iterator const &) const; | |||
bool operator!=(movable_input_iterator const &) const; | |||
T && operator*() const; | |||
}; | |||
} // namespace detail | |||
/// \endcond | |||
/// \addtogroup group-range | |||
/// @{ | |||
// std::array is a semi_container, native arrays are not. | |||
// clang-format off | |||
CPP_def | |||
( | |||
template(typename T) | |||
concept semi_container, | |||
forward_range<T> && default_constructible<uncvref_t<T>> && | |||
movable<uncvref_t<T>> && | |||
!view_<T> | |||
); | |||
// std::vector is a container, std::array is not | |||
CPP_def | |||
( | |||
template(typename T) | |||
concept container, | |||
semi_container<T> && | |||
constructible_from< | |||
uncvref_t<T>, | |||
detail::movable_input_iterator<range_value_t<T>>, | |||
detail::movable_input_iterator<range_value_t<T>>> | |||
); | |||
CPP_def | |||
( | |||
template(typename C) | |||
concept reservable, | |||
requires (C &c, C const &cc, range_size_t<C> s) | |||
( | |||
c.reserve(s), | |||
cc.capacity(), | |||
cc.max_size(), | |||
concepts::requires_<same_as<decltype(cc.capacity()), range_size_t<C>>>, | |||
concepts::requires_<same_as<decltype(cc.max_size()), range_size_t<C>>> | |||
) && | |||
container<C> && sized_range<C> | |||
); | |||
CPP_def | |||
( | |||
template(typename C, typename I) | |||
concept reservable_with_assign, | |||
requires (C &c, I i) | |||
( | |||
c.assign(i, i) | |||
) && | |||
reservable<C> && input_iterator<I> | |||
); | |||
CPP_def | |||
( | |||
template(typename C) | |||
concept random_access_reservable, | |||
reservable<C> && random_access_range<C> | |||
); | |||
// clang-format on | |||
/// \cond | |||
namespace detail | |||
{ | |||
template<typename T> | |||
auto is_lvalue_container_like(T &) noexcept -> CPP_ret(std::true_type)( // | |||
requires container<T>) | |||
{ | |||
return {}; | |||
} | |||
template<typename T> | |||
auto is_lvalue_container_like(reference_wrapper<T>) noexcept | |||
-> CPP_ret(meta::not_<std::is_rvalue_reference<T>>)( // | |||
requires container<T>) | |||
{ | |||
return {}; | |||
} | |||
template<typename T> | |||
auto is_lvalue_container_like(std::reference_wrapper<T>) noexcept | |||
-> CPP_ret(std::true_type)( // | |||
requires container<T>) | |||
{ | |||
return {}; | |||
} | |||
template<typename T> | |||
auto is_lvalue_container_like(ref_view<T>) noexcept -> CPP_ret(std::true_type)( // | |||
requires container<T>) | |||
{ | |||
return {}; | |||
} | |||
template<typename T> | |||
using is_lvalue_container_like_t = | |||
decltype(detail::is_lvalue_container_like(std::declval<T>())); | |||
} // namespace detail | |||
/// \endcond | |||
// clang-format off | |||
CPP_def | |||
( | |||
template(typename T) | |||
concept lvalue_container_like, | |||
implicitly_convertible_to<detail::is_lvalue_container_like_t<T>, | |||
std::true_type> && | |||
forward_range<T> | |||
); | |||
// clang-format on | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,66 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_DROP_HPP | |||
#define RANGES_V3_ACTION_DROP_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct drop_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename Int> | |||
static auto CPP_fun(bind)(drop_fn drop, Int n)( // | |||
requires integral<Int>) | |||
{ | |||
return bind_back(drop, n); | |||
} | |||
public: | |||
template<typename Rng> | |||
auto operator()(Rng && rng, range_difference_t<Rng> n) const | |||
-> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && | |||
erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>>) | |||
{ | |||
RANGES_EXPECT(n >= 0); | |||
ranges::actions::erase( | |||
rng, begin(rng), ranges::next(begin(rng), n, end(rng))); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates drop_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<drop_fn>, drop) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,65 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_DROP_WHILE_HPP | |||
#define RANGES_V3_ACTION_DROP_WHILE_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/algorithm/find_if_not.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct drop_while_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename Fun> | |||
static auto CPP_fun(bind)(drop_while_fn drop_while, Fun fun)( // | |||
requires(!range<Fun>)) | |||
{ | |||
return bind_back(drop_while, std::move(fun)); | |||
} | |||
public: | |||
template<typename Rng, typename Fun> | |||
auto operator()(Rng && rng, Fun fun) const -> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && | |||
indirect_unary_predicate<Fun, iterator_t<Rng>> && | |||
erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>>) | |||
{ | |||
ranges::actions::erase( | |||
rng, begin(rng), find_if_not(begin(rng), end(rng), std::move(fun))); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates drop_while_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<drop_while_fn>, drop_while) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,76 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_ERASE_HPP | |||
#define RANGES_V3_ACTION_ERASE_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/insert.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \cond | |||
namespace adl_erase_detail | |||
{ | |||
template<typename Cont, typename I, typename S> | |||
auto erase(Cont && cont, I first, S last) // | |||
-> CPP_ret(decltype(unwrap_reference(cont).erase(first, last)))( // | |||
requires lvalue_container_like<Cont> && forward_iterator<I> && | |||
sentinel_for<S, I>) | |||
{ | |||
return unwrap_reference(cont).erase(first, last); | |||
} | |||
struct erase_fn | |||
{ | |||
template<typename Rng, typename I, typename S> | |||
auto operator()(Rng && rng, I first, S last) const | |||
-> CPP_ret(decltype(erase((Rng &&) rng, first, last)))( // | |||
requires range<Rng> && forward_iterator<I> && sentinel_for<S, I>) | |||
{ | |||
return erase(static_cast<Rng &&>(rng), first, last); | |||
} | |||
}; | |||
} // namespace adl_erase_detail | |||
/// \endcond | |||
/// \ingroup group-actions | |||
RANGES_INLINE_VARIABLE(adl_erase_detail::erase_fn, erase) | |||
namespace actions | |||
{ | |||
using ranges::erase; | |||
} | |||
/// \addtogroup group-range | |||
/// @{ | |||
// clang-format off | |||
CPP_def | |||
( | |||
template(typename Rng, typename I, typename S) | |||
concept erasable_range, | |||
requires (Rng &&rng, I first, S last) | |||
( | |||
ranges::erase(static_cast<Rng &&>(rng), first, last) | |||
) && | |||
range<Rng> | |||
); | |||
// clang-format on | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,301 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_INSERT_HPP | |||
#define RANGES_V3_ACTION_INSERT_HPP | |||
#include <initializer_list> | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/concepts.hpp> | |||
#include <range/v3/algorithm/max.hpp> | |||
#include <range/v3/iterator/common_iterator.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \cond | |||
namespace adl_insert_detail | |||
{ | |||
template<typename Cont, typename... Args> | |||
using insert_result_t = decltype( | |||
unwrap_reference(std::declval<Cont>()).insert(std::declval<Args>()...)); | |||
template<typename Cont, typename T> | |||
auto insert(Cont && cont, T && t) -> CPP_ret(insert_result_t<Cont &, T>)( // | |||
requires lvalue_container_like<Cont> && | |||
(!range<T> && constructible_from<range_value_t<Cont>, T>)) | |||
{ | |||
return unwrap_reference(cont).insert(static_cast<T &&>(t)); | |||
} | |||
template<typename Cont, typename I, typename S> | |||
auto insert(Cont && cont, I i, S j) | |||
-> CPP_ret(insert_result_t<Cont &, detail::cpp17_iterator_t<I, S>, | |||
detail::cpp17_iterator_t<I, S>>)( // | |||
requires lvalue_container_like<Cont> && sentinel_for<S, I> && (!range<S>)) | |||
{ | |||
return unwrap_reference(cont).insert(detail::cpp17_iterator_t<I, S>{i}, | |||
detail::cpp17_iterator_t<I, S>{j}); | |||
} | |||
template<typename Cont, typename Rng> | |||
auto insert(Cont && cont, Rng && rng) | |||
-> CPP_ret(insert_result_t<Cont &, detail::range_cpp17_iterator_t<Rng>, | |||
detail::range_cpp17_iterator_t<Rng>>)( // | |||
requires lvalue_container_like<Cont> && range<Rng>) | |||
{ | |||
return unwrap_reference(cont).insert( | |||
detail::range_cpp17_iterator_t<Rng>{ranges::begin(rng)}, | |||
detail::range_cpp17_iterator_t<Rng>{ranges::end(rng)}); | |||
} | |||
template<typename Cont, typename I, typename T> | |||
auto insert(Cont && cont, I p, T && t) | |||
-> CPP_ret(insert_result_t<Cont &, I, T>)( // | |||
requires lvalue_container_like<Cont> && input_iterator<I> && | |||
(!range<T> && constructible_from<range_value_t<Cont>, T>)) | |||
{ | |||
return unwrap_reference(cont).insert(p, static_cast<T &&>(t)); | |||
} | |||
template<typename Cont, typename I, typename N, typename T> | |||
auto insert(Cont && cont, I p, N n, T && t) | |||
-> CPP_ret(insert_result_t<Cont &, I, N, T>)( // | |||
requires lvalue_container_like<Cont> && input_iterator<I> && | |||
integral<N> && constructible_from<range_value_t<Cont>, T>) | |||
{ | |||
return unwrap_reference(cont).insert(p, n, static_cast<T &&>(t)); | |||
} | |||
/// \cond | |||
namespace detail | |||
{ | |||
using ranges::detail::cpp17_iterator_t; | |||
using ranges::detail::range_cpp17_iterator_t; | |||
template<typename Cont, typename P> | |||
auto insert_reserve_helper(Cont & cont, P const p, | |||
range_size_t<Cont> const delta) | |||
-> CPP_ret(iterator_t<Cont>)( // | |||
requires container<Cont> && input_iterator<P> && | |||
random_access_reservable<Cont>) | |||
{ | |||
auto const old_size = ranges::size(cont); | |||
auto const max_size = cont.max_size(); | |||
RANGES_EXPECT(delta <= max_size - old_size); | |||
auto const new_size = old_size + delta; | |||
auto const old_capacity = cont.capacity(); | |||
auto const index = p - ranges::begin(cont); | |||
if(old_capacity < new_size) | |||
{ | |||
auto const new_capacity = | |||
(old_capacity <= max_size / 3 * 2) | |||
? ranges::max(old_capacity + old_capacity / 2, new_size) | |||
: max_size; | |||
cont.reserve(new_capacity); | |||
} | |||
return ranges::begin(cont) + index; | |||
} | |||
template<typename Cont, typename P, typename I, typename S> | |||
auto insert_impl(Cont && cont, P p, I i, S j, std::false_type) | |||
-> CPP_ret(decltype(unwrap_reference(cont).insert( | |||
p, cpp17_iterator_t<I, S>{i}, cpp17_iterator_t<I, S>{j})))( // | |||
requires sentinel_for<S, I> && (!range<S>)) | |||
{ | |||
using C = cpp17_iterator_t<I, S>; | |||
return unwrap_reference(cont).insert(p, C{i}, C{j}); | |||
} | |||
template<typename Cont, typename P, typename I, typename S> | |||
auto insert_impl(Cont && cont_, P p, I i, S j, std::true_type) | |||
-> CPP_ret(decltype(unwrap_reference(cont_).insert( | |||
ranges::begin(unwrap_reference(cont_)), cpp17_iterator_t<I, S>{i}, | |||
cpp17_iterator_t<I, S>{j})))( // | |||
requires sized_sentinel_for<S, I> && random_access_reservable<Cont> && | |||
(!range<S>)) | |||
{ | |||
using C = cpp17_iterator_t<I, S>; | |||
auto && cont = unwrap_reference(cont_); | |||
auto const delta = static_cast<range_size_t<Cont>>(j - i); | |||
auto pos = insert_reserve_helper(cont, std::move(p), delta); | |||
return cont.insert(pos, C{std::move(i)}, C{std::move(j)}); | |||
} | |||
template<typename Cont, typename I, typename Rng> | |||
auto insert_impl(Cont && cont, I p, Rng && rng, std::false_type) | |||
-> CPP_ret(decltype(unwrap_reference(cont).insert( | |||
p, range_cpp17_iterator_t<Rng>{ranges::begin(rng)}, | |||
range_cpp17_iterator_t<Rng>{ranges::end(rng)})))( // | |||
requires range<Rng>) | |||
{ | |||
using C = range_cpp17_iterator_t<Rng>; | |||
return unwrap_reference(cont).insert( | |||
p, C{ranges::begin(rng)}, C{ranges::end(rng)}); | |||
} | |||
template<typename Cont, typename I, typename Rng> | |||
auto insert_impl(Cont && cont_, I p, Rng && rng, std::true_type) | |||
-> CPP_ret(decltype(unwrap_reference(cont_).insert( | |||
begin(unwrap_reference(cont_)), | |||
range_cpp17_iterator_t<Rng>{ranges::begin(rng)}, | |||
range_cpp17_iterator_t<Rng>{ranges::end(rng)})))( // | |||
requires random_access_reservable<Cont> && sized_range<Rng>) | |||
{ | |||
using C = range_cpp17_iterator_t<Rng>; | |||
auto && cont = unwrap_reference(cont_); | |||
auto const delta = static_cast<range_size_t<Cont>>(ranges::size(rng)); | |||
auto pos = insert_reserve_helper(cont, std::move(p), delta); | |||
return cont.insert(pos, C{ranges::begin(rng)}, C{ranges::end(rng)}); | |||
} | |||
} // namespace detail | |||
/// \endcond | |||
template<typename Cont, typename P, typename I, typename S> | |||
auto insert(Cont && cont, P p, I i, S j) -> CPP_ret(decltype(detail::insert_impl( | |||
static_cast<Cont &&>(cont), std::move(p), std::move(i), std::move(j), | |||
meta::bool_<random_access_reservable<Cont> && | |||
sized_sentinel_for<S, I>>{})))( // | |||
requires lvalue_container_like<Cont> && input_iterator<P> && | |||
sentinel_for<S, I> && | |||
(!range<S>)) | |||
{ | |||
return detail::insert_impl(static_cast<Cont &&>(cont), | |||
std::move(p), | |||
std::move(i), | |||
std::move(j), | |||
meta::bool_ < random_access_reservable<Cont> && | |||
sized_sentinel_for<S, I>> {}); | |||
} | |||
template<typename Cont, typename I, typename Rng> | |||
auto insert(Cont && cont, I p, Rng && rng) | |||
-> CPP_ret(decltype(detail::insert_impl( | |||
static_cast<Cont &&>(cont), std::move(p), static_cast<Rng &&>(rng), | |||
meta::bool_<random_access_reservable<Cont> && sized_range<Rng>>{})))( // | |||
requires lvalue_container_like<Cont> && input_iterator<I> && range<Rng>) | |||
{ | |||
return detail::insert_impl(static_cast<Cont &&>(cont), | |||
std::move(p), | |||
static_cast<Rng &&>(rng), | |||
meta::bool_ < random_access_reservable<Cont> && | |||
sized_range<Rng>> {}); | |||
} | |||
struct insert_fn | |||
{ | |||
template<typename Rng, typename... Args> | |||
using insert_result_t = | |||
decltype(insert(std::declval<Rng>(), std::declval<Args>()...)); | |||
template<typename Rng, typename T> | |||
auto operator()(Rng && rng, T && t) const | |||
-> CPP_ret(insert_result_t<Rng, T>)( // | |||
requires range<Rng> && | |||
(!range<T>)&&constructible_from<range_value_t<Rng>, T>) | |||
{ | |||
return insert(static_cast<Rng &&>(rng), static_cast<T &&>(t)); | |||
} | |||
template<typename Rng, typename Rng2> | |||
auto operator()(Rng && rng, Rng2 && rng2) const | |||
-> CPP_ret(insert_result_t<Rng, Rng2>)( // | |||
requires range<Rng> && range<Rng2>) | |||
{ | |||
static_assert(!is_infinite<Rng>::value, | |||
"Attempting to insert an infinite range into a container"); | |||
return insert(static_cast<Rng &&>(rng), static_cast<Rng2 &&>(rng2)); | |||
} | |||
template<typename Rng, typename T> | |||
auto operator()(Rng && rng, std::initializer_list<T> rng2) const | |||
-> CPP_ret(insert_result_t<Rng, std::initializer_list<T> &>)( // | |||
requires range<Rng>) | |||
{ | |||
return insert(static_cast<Rng &&>(rng), rng2); | |||
} | |||
template<typename Rng, typename I, typename S> | |||
auto operator()(Rng && rng, I i, S j) const | |||
-> CPP_ret(insert_result_t<Rng, I, S>)( // | |||
requires range<Rng> && sentinel_for<S, I> && (!range<S>)) | |||
{ | |||
return insert(static_cast<Rng &&>(rng), std::move(i), std::move(j)); | |||
} | |||
template<typename Rng, typename I, typename T> | |||
auto operator()(Rng && rng, I p, T && t) const | |||
-> CPP_ret(insert_result_t<Rng, I, T>)( // | |||
requires range<Rng> && input_iterator<I> && | |||
(!range<T>)&&constructible_from<range_value_t<Rng>, T>) | |||
{ | |||
return insert( | |||
static_cast<Rng &&>(rng), std::move(p), static_cast<T &&>(t)); | |||
} | |||
template<typename Rng, typename I, typename Rng2> | |||
auto operator()(Rng && rng, I p, Rng2 && rng2) const | |||
-> CPP_ret(insert_result_t<Rng, I, Rng2>)( // | |||
requires range<Rng> && input_iterator<I> && range<Rng2>) | |||
{ | |||
static_assert(!is_infinite<Rng>::value, | |||
"Attempting to insert an infinite range into a container"); | |||
return insert( | |||
static_cast<Rng &&>(rng), std::move(p), static_cast<Rng2 &&>(rng2)); | |||
} | |||
template<typename Rng, typename I, typename T> | |||
auto operator()(Rng && rng, I p, std::initializer_list<T> rng2) const | |||
-> CPP_ret(insert_result_t<Rng, I, std::initializer_list<T> &>)( // | |||
requires range<Rng> && input_iterator<I>) | |||
{ | |||
return insert(static_cast<Rng &&>(rng), std::move(p), rng2); | |||
} | |||
template<typename Rng, typename I, typename N, typename T> | |||
auto operator()(Rng && rng, I p, N n, T && t) const | |||
-> CPP_ret(insert_result_t<Rng, I, N, T>)( // | |||
requires range<Rng> && input_iterator<I> && integral<N> && | |||
(!range<T>)&&constructible_from<range_value_t<Rng>, T>) | |||
{ | |||
return insert( | |||
static_cast<Rng &&>(rng), std::move(p), n, static_cast<T &&>(t)); | |||
} | |||
template<typename Rng, typename P, typename I, typename S> | |||
auto operator()(Rng && rng, P p, I i, S j) const | |||
-> CPP_ret(insert_result_t<Rng, P, I, S>)( // | |||
requires range<Rng> && input_iterator<P> && sentinel_for<S, I> && | |||
(!range<S>)) | |||
{ | |||
return insert( | |||
static_cast<Rng &&>(rng), std::move(p), std::move(i), std::move(j)); | |||
} | |||
}; | |||
} // namespace adl_insert_detail | |||
/// \endcond | |||
/// \ingroup group-actions | |||
RANGES_INLINE_VARIABLE(adl_insert_detail::insert_fn, insert) | |||
namespace actions | |||
{ | |||
using ranges::insert; | |||
} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,65 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_JOIN_HPP | |||
#define RANGES_V3_ACTION_JOIN_HPP | |||
#include <vector> | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/concepts.hpp> | |||
#include <range/v3/action/push_back.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
template<typename Rng> | |||
using join_action_value_t_ = | |||
meta::if_c<(bool)ranges::container<range_value_t<Rng>>, range_value_t<Rng>, | |||
std::vector<range_value_t<range_value_t<Rng>>>>; | |||
struct join_fn | |||
{ | |||
public: | |||
template<typename Rng> | |||
auto operator()(Rng && rng) const -> CPP_ret(join_action_value_t_<Rng>)( // | |||
requires input_range<Rng> && input_range<range_value_t<Rng>> && | |||
semiregular<join_action_value_t_<Rng>>) | |||
{ | |||
join_action_value_t_<Rng> ret; | |||
auto last = ranges::end(rng); | |||
for(auto it = begin(rng); it != last; ++it) | |||
push_back(ret, *it); | |||
return ret; | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates join_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<join_fn>, join) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,134 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_PUSH_BACK_HPP | |||
#define RANGES_V3_ACTION_PUSH_BACK_HPP | |||
#include <utility> | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/insert.hpp> | |||
#include <range/v3/detail/with_braced_init_args.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \cond | |||
namespace adl_push_back_detail | |||
{ | |||
template<typename Cont, typename T> | |||
using push_back_t = decltype(static_cast<void>( | |||
unwrap_reference(std::declval<Cont &>()).push_back(std::declval<T>()))); | |||
template<typename Cont, typename Rng> | |||
using insert_t = decltype(static_cast<void>( | |||
ranges::insert(std::declval<Cont &>(), std::declval<sentinel_t<Cont>>(), | |||
std::declval<Rng>()))); | |||
template<typename Cont, typename T> | |||
auto push_back(Cont && cont, T && t) -> CPP_ret(push_back_t<Cont, T>)( // | |||
requires lvalue_container_like<Cont> && | |||
(!range<T>)&&constructible_from<range_value_t<Cont>, T>) | |||
{ | |||
unwrap_reference(cont).push_back(static_cast<T &&>(t)); | |||
} | |||
template<typename Cont, typename Rng> | |||
auto push_back(Cont && cont, Rng && rng) -> CPP_ret(insert_t<Cont, Rng>)( // | |||
requires lvalue_container_like<Cont> && range<Rng>) | |||
{ | |||
ranges::insert(cont, end(cont), static_cast<Rng &&>(rng)); | |||
} | |||
/// \cond | |||
// clang-format off | |||
CPP_def | |||
( | |||
template(typename Rng, typename T) | |||
concept can_push_back_, | |||
requires (Rng &&rng, T &&t) | |||
( | |||
push_back(rng, (T &&) t) | |||
) | |||
); | |||
// clang-format on | |||
/// \endcond | |||
struct push_back_fn | |||
{ | |||
private: | |||
friend actions::action_access; | |||
template<typename T> | |||
static auto bind(push_back_fn push_back, T && val) | |||
{ | |||
return bind_back(push_back, static_cast<T &&>(val)); | |||
} | |||
#ifdef RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||
template<typename T, std::size_t N> | |||
struct lamduh | |||
{ | |||
T (&val_)[N]; | |||
template<typename Rng> | |||
auto operator()(Rng && rng) const | |||
-> invoke_result_t<push_back_fn, Rng, T (&)[N]> | |||
{ | |||
return push_back_fn{}(static_cast<Rng &&>(rng), val_); | |||
} | |||
}; | |||
template<typename T, std::size_t N> | |||
static lamduh<T, N> bind(push_back_fn, T (&val)[N]) | |||
{ | |||
return {val}; | |||
} | |||
#else // ^^^ workaround / no workaround vvv | |||
template<typename T, std::size_t N> | |||
static auto bind(push_back_fn, T (&val)[N]) | |||
{ | |||
return [&val](auto && rng) | |||
-> invoke_result_t<push_back_fn, decltype(rng), T(&)[N]> | |||
{ | |||
return push_back_fn{}(static_cast<decltype(rng)>(rng), val); | |||
}; | |||
} | |||
#endif // RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||
public: | |||
template<typename Rng, typename T> | |||
auto operator()(Rng && rng, T && t) const -> CPP_ret(Rng)( // | |||
requires input_range<Rng> && can_push_back_<Rng, T> && | |||
(range<T> || constructible_from<range_value_t<Rng>, T>)) | |||
{ | |||
push_back(rng, static_cast<T &&>(t)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
} // namespace adl_push_back_detail | |||
/// \endcond | |||
namespace actions | |||
{ | |||
/// \ingroup group-actions | |||
RANGES_INLINE_VARIABLE( | |||
detail::with_braced_init_args<action<adl_push_back_detail::push_back_fn>>, | |||
push_back) | |||
} // namespace actions | |||
using actions::push_back; | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,132 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_PUSH_FRONT_HPP | |||
#define RANGES_V3_ACTION_PUSH_FRONT_HPP | |||
#include <utility> | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/insert.hpp> | |||
#include <range/v3/detail/with_braced_init_args.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \cond | |||
namespace adl_push_front_detail | |||
{ | |||
template<typename Cont, typename T> | |||
using push_front_t = decltype(static_cast<void>( | |||
unwrap_reference(std::declval<Cont &>()).push_front(std::declval<T>()))); | |||
template<typename Cont, typename Rng> | |||
using insert_t = decltype(static_cast<void>( | |||
ranges::insert(std::declval<Cont &>(), std::declval<iterator_t<Cont>>(), | |||
std::declval<Rng>()))); | |||
template<typename Cont, typename T> | |||
auto push_front(Cont && cont, T && t) -> CPP_ret(push_front_t<Cont, T>)( // | |||
requires lvalue_container_like<Cont> && | |||
(!range<T>)&&constructible_from<range_value_t<Cont>, T>) | |||
{ | |||
unwrap_reference(cont).push_front(static_cast<T &&>(t)); | |||
} | |||
template<typename Cont, typename Rng> | |||
auto push_front(Cont && cont, Rng && rng) -> CPP_ret(insert_t<Cont, Rng>)( // | |||
requires lvalue_container_like<Cont> && range<Rng>) | |||
{ | |||
ranges::insert(cont, begin(cont), static_cast<Rng &&>(rng)); | |||
} | |||
// clang-format off | |||
CPP_def | |||
( | |||
template(typename Rng, typename T) | |||
concept can_push_front_, | |||
requires (Rng &&rng, T &&t) | |||
( | |||
push_front(rng, (T &&) t) | |||
) | |||
); | |||
// clang-format on | |||
struct push_front_fn | |||
{ | |||
private: | |||
friend actions::action_access; | |||
template<typename T> | |||
static auto bind(push_front_fn push_front, T && val) | |||
{ | |||
return bind_back(push_front, static_cast<T &&>(val)); | |||
} | |||
#ifdef RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||
template<typename T, std::size_t N> | |||
struct lamduh | |||
{ | |||
T (&val_)[N]; | |||
template<typename Rng> | |||
auto operator()(Rng && rng) const | |||
-> invoke_result_t<push_front_fn, Rng, T (&)[N]> | |||
{ | |||
return push_front_fn{}(static_cast<Rng &&>(rng), val_); | |||
} | |||
}; | |||
template<typename T, std::size_t N> | |||
static lamduh<T, N> bind(push_front_fn, T (&val)[N]) | |||
{ | |||
return {val}; | |||
} | |||
#else // ^^^ workaround / no workaround vvv | |||
template<typename T, std::size_t N> | |||
static auto bind(push_front_fn, T (&val)[N]) | |||
{ | |||
return [&val](auto && rng) | |||
-> invoke_result_t<push_front_fn, decltype(rng), T(&)[N]> | |||
{ | |||
return push_front_fn{}(static_cast<decltype(rng)>(rng), val); | |||
}; | |||
} | |||
#endif // RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||
public: | |||
template<typename Rng, typename T> | |||
auto operator()(Rng && rng, T && t) const -> CPP_ret(Rng)( // | |||
requires input_range<Rng> && can_push_front_<Rng, T> && | |||
(range<T> || constructible_from<range_value_t<Rng>, T>)) | |||
{ | |||
push_front(rng, static_cast<T &&>(t)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
} // namespace adl_push_front_detail | |||
/// \endcond | |||
namespace actions | |||
{ | |||
/// \ingroup group-actions | |||
RANGES_INLINE_VARIABLE( | |||
detail::with_braced_init_args<action<adl_push_front_detail::push_front_fn>>, | |||
push_front) | |||
} // namespace actions | |||
using actions::push_front; | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,72 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Andrey Diduh 2019 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_REMOVE_HPP | |||
#define RANGES_V3_ACTION_REMOVE_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/algorithm/remove.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct remove_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename V, typename P> | |||
static auto CPP_fun(bind)(remove_fn remove, V && value, P proj)( // | |||
requires(!range<V>)) | |||
{ | |||
return bind_back(remove, static_cast<V &&>(value), std::move(proj)); | |||
} | |||
template<typename V> | |||
static auto bind(remove_fn remove, V && value) | |||
{ | |||
return bind_back(remove, static_cast<V &&>(value), identity{}); | |||
} | |||
public: | |||
template<typename Rng, typename V, typename P = identity> | |||
auto operator()(Rng && rng, V const & value, P proj = {}) const | |||
-> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && permutable<iterator_t<Rng>> && | |||
erasable_range<Rng, iterator_t<Rng>, sentinel_t<Rng>> && | |||
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, | |||
V const *>) | |||
{ | |||
auto it = ranges::remove(rng, value, std::move(proj)); | |||
ranges::erase(rng, it, ranges::end(rng)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \sa action | |||
/// \sa with_braced_init_args | |||
RANGES_INLINE_VARIABLE(action<remove_fn>, remove) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,69 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_REMOVE_IF_HPP | |||
#define RANGES_V3_ACTION_REMOVE_IF_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/algorithm/remove_if.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
// TODO Look at all the special cases handled by erase_if in Library Fundamentals 2 | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct remove_if_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename C, typename P = identity> | |||
static auto CPP_fun(bind)(remove_if_fn remove_if, C pred, P proj = P{})( // | |||
requires(!range<C>)) | |||
{ | |||
return bind_back(remove_if, std::move(pred), std::move(proj)); | |||
} | |||
public: | |||
template<typename Rng, typename C, typename P = identity> | |||
auto operator()(Rng && rng, C pred, P proj = P{}) const -> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && | |||
erasable_range<Rng &, iterator_t<Rng>, iterator_t<Rng>> && | |||
permutable<iterator_t<Rng>> && | |||
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
auto it = ranges::remove_if(rng, std::move(pred), std::move(proj)); | |||
ranges::erase(rng, it, ranges::end(rng)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<remove_if_fn>, remove_if) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,56 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// Copyright Gonzalo Brito Gadeschi 2017 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_REVERSE_HPP | |||
#define RANGES_V3_ACTION_REVERSE_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/algorithm/reverse.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
/// Reversed the source range in-place. | |||
struct reverse_fn | |||
{ | |||
private: | |||
friend action_access; | |||
public: | |||
template<typename Rng> | |||
auto operator()(Rng && rng) const -> CPP_ret(Rng)( // | |||
requires bidirectional_range<Rng> && permutable<iterator_t<Rng>>) | |||
{ | |||
ranges::reverse(rng); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates reverse_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<reverse_fn>, reverse) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,96 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Filip Matzner 2015 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_SHUFFLE_HPP | |||
#define RANGES_V3_ACTION_SHUFFLE_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/algorithm/shuffle.hpp> | |||
#include <range/v3/functional/bind.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct shuffle_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename Gen> | |||
static auto CPP_fun(bind)(shuffle_fn shuffle, Gen && gen)( // | |||
requires uniform_random_bit_generator<Gen>) | |||
{ | |||
return bind_back(shuffle, static_cast<Gen &&>(gen)); | |||
} | |||
#ifdef RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||
template<typename Gen> | |||
struct lamduh | |||
{ | |||
Gen & gen_; | |||
template<typename Rng> | |||
auto operator()(Rng && rng) const | |||
-> invoke_result_t<shuffle_fn, Rng, Gen &> | |||
{ | |||
return shuffle_fn{}(static_cast<Rng &&>(rng), gen_); | |||
} | |||
}; | |||
template<typename Gen> | |||
static lamduh<Gen> CPP_fun(bind)(shuffle_fn, Gen & gen)( // | |||
requires uniform_random_bit_generator<Gen>) | |||
{ | |||
return {gen}; | |||
} | |||
#else // ^^^ workaround / no workaround vvv | |||
template<typename Gen> | |||
static auto CPP_fun(bind)(shuffle_fn, Gen & gen)( // | |||
requires uniform_random_bit_generator<Gen>) | |||
{ | |||
return [&gen](auto && rng) | |||
-> invoke_result_t<shuffle_fn, decltype(rng), Gen &> { | |||
return shuffle_fn{}(static_cast<decltype(rng)>(rng), gen); | |||
}; | |||
} | |||
#endif // RANGES_WORKAROUND_MSVC_OLD_LAMBDA | |||
public: | |||
template<typename Rng, typename Gen> | |||
auto operator()(Rng && rng, Gen && gen) const -> CPP_ret(Rng)( // | |||
requires random_access_range<Rng> && permutable<iterator_t<Rng>> && | |||
uniform_random_bit_generator<std::remove_reference_t<Gen>> && | |||
convertible_to<invoke_result_t<Gen &>, range_difference_t<Rng>>) | |||
{ | |||
ranges::shuffle(rng, static_cast<Gen &&>(gen)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates shuffle_fn | |||
/// \sa `action` | |||
RANGES_INLINE_VARIABLE(action<shuffle_fn>, shuffle) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,154 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_SLICE_HPP | |||
#define RANGES_V3_ACTION_SLICE_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
#include <range/v3/view/interface.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct slice_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename D> | |||
using diff_t = range_difference_t<D>; | |||
// Overloads for the pipe syntax: rng | actions::slice(from, to) | |||
template<typename D> | |||
static auto CPP_fun(bind)(slice_fn slice, D from, D to)( // | |||
requires integral<D>) | |||
{ | |||
return bind_back(slice, from, to); | |||
} | |||
template<typename D> | |||
static auto CPP_fun(bind)(slice_fn slice, D from, detail::from_end_<D> to)( // | |||
requires integral<D>) | |||
{ | |||
return bind_back(slice, from, to); | |||
} | |||
template<typename D> | |||
static auto CPP_fun(bind)(slice_fn slice, detail::from_end_<D> from, | |||
detail::from_end_<D> to)( // | |||
requires integral<D>) | |||
{ | |||
return bind_back(slice, from, to); | |||
} | |||
template<typename D> | |||
static auto CPP_fun(bind)(slice_fn slice, D from, end_fn const & to)( // | |||
requires integral<D>) | |||
{ | |||
return bind_back(slice, from, to); | |||
} | |||
template<typename D> | |||
static auto CPP_fun(bind)(slice_fn slice, detail::from_end_<D> from, | |||
end_fn const & to)( // | |||
requires integral<D>) | |||
{ | |||
return bind_back(slice, from, to); | |||
} | |||
public: | |||
template<typename Rng, typename I = iterator_t<Rng>> | |||
auto operator()(Rng && rng, diff_t<Rng> from, diff_t<Rng> to) const | |||
-> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && erasable_range<Rng &, I, I>) | |||
{ | |||
RANGES_EXPECT(0 <= from && 0 <= to && from <= to); | |||
RANGES_EXPECT(!sized_range<Rng> || to <= distance(rng)); | |||
ranges::actions::erase(rng, begin(rng), next(begin(rng), from)); | |||
ranges::actions::erase(rng, next(begin(rng), to - from), end(rng)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
template<typename Rng, typename I = iterator_t<Rng>> | |||
auto operator()(Rng && rng, diff_t<Rng> from, | |||
detail::from_end_<diff_t<Rng>> to) const -> CPP_ret(Rng)( // | |||
requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>) | |||
{ | |||
RANGES_EXPECT(0 <= from && to.dist_ <= 0); | |||
RANGES_EXPECT(!sized_range<Rng> || from - to.dist_ <= distance(rng)); | |||
ranges::actions::erase(rng, begin(rng), next(begin(rng), from)); | |||
if(to.dist_ != 0) | |||
{ | |||
auto const last = next(begin(rng), end(rng)); | |||
ranges::actions::erase(rng, prev(last, -to.dist_), last); | |||
} | |||
return static_cast<Rng &&>(rng); | |||
} | |||
template<typename Rng, typename I = iterator_t<Rng>> | |||
auto operator()(Rng && rng, detail::from_end_<diff_t<Rng>> from, | |||
detail::from_end_<diff_t<Rng>> to) const -> CPP_ret(Rng)( // | |||
requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>) | |||
{ | |||
RANGES_EXPECT(from.dist_ <= 0 && to.dist_ <= 0 && from.dist_ <= to.dist_); | |||
RANGES_EXPECT(!sized_range<Rng> || 0 <= distance(rng) + from.dist_); | |||
auto last = next(begin(rng), end(rng)); | |||
ranges::actions::erase(rng, prev(last, -to.dist_), last); | |||
last = next(begin(rng), end(rng)); | |||
ranges::actions::erase( | |||
rng, begin(rng), prev(last, to.dist_ - from.dist_)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
template<typename Rng, typename I = iterator_t<Rng>> | |||
auto operator()(Rng && rng, diff_t<Rng> from, end_fn const &) const | |||
-> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && erasable_range<Rng &, I, I>) | |||
{ | |||
RANGES_EXPECT(0 <= from); | |||
RANGES_EXPECT(!sized_range<Rng> || from <= distance(rng)); | |||
ranges::actions::erase(rng, begin(rng), next(begin(rng), from)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
template<typename Rng, typename I = iterator_t<Rng>> | |||
auto operator()(Rng && rng, detail::from_end_<diff_t<Rng>> from, | |||
end_fn const &) const -> CPP_ret(Rng)( // | |||
requires bidirectional_range<Rng> && erasable_range<Rng &, I, I>) | |||
{ | |||
RANGES_EXPECT(from.dist_ <= 0); | |||
RANGES_EXPECT(!sized_range<Rng> || 0 <= distance(rng) + from.dist_); | |||
auto const last = next(begin(rng), end(rng)); | |||
ranges::actions::erase(rng, begin(rng), prev(last, -from.dist_)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates slice_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<slice_fn>, slice) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,64 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_SORT_HPP | |||
#define RANGES_V3_ACTION_SORT_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/algorithm/sort.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct sort_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename C, typename P = identity> | |||
static auto CPP_fun(bind)(sort_fn sort, C pred, P proj = {})( // | |||
requires(!range<C>)) | |||
{ | |||
return bind_back(sort, std::move(pred), std::move(proj)); | |||
} | |||
public: | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto operator()(Rng && rng, C pred = {}, P proj = {}) const | |||
-> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||
{ | |||
ranges::sort(rng, std::move(pred), std::move(proj)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates sort_fn | |||
/// \sa `action` | |||
RANGES_INLINE_VARIABLE(action<sort_fn>, sort) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,78 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_SPLIT_HPP | |||
#define RANGES_V3_ACTION_SPLIT_HPP | |||
#include <vector> | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/concepts.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/conversion.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
#include <range/v3/view/split.hpp> | |||
#include <range/v3/view/transform.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct split_fn | |||
{ | |||
private: | |||
template<typename Rng> | |||
using split_value_t = meta::if_c<(bool)ranges::container<Rng>, uncvref_t<Rng>, | |||
std::vector<range_value_t<Rng>>>; | |||
public: | |||
// BUGBUG something is not right with the actions. It should be possible | |||
// to move a container into a split and have elements moved into the result. | |||
template<typename Rng> | |||
auto operator()(Rng && rng, range_value_t<Rng> val) const | |||
-> CPP_ret(std::vector<split_value_t<Rng>>)( // | |||
requires input_range<Rng> && indirectly_comparable< | |||
iterator_t<Rng>, range_value_t<Rng> const *, ranges::equal_to>) | |||
{ | |||
return views::split(rng, std::move(val)) | | |||
views::transform(to<split_value_t<Rng>>()) | to_vector; | |||
} | |||
template<typename Rng, typename Pattern> | |||
auto operator()(Rng && rng, Pattern && pattern) const | |||
-> CPP_ret(std::vector<split_value_t<Rng>>)( // | |||
requires input_range<Rng> && viewable_range<Pattern> && | |||
forward_range<Pattern> && indirectly_comparable< | |||
iterator_t<Rng>, iterator_t<Pattern>, ranges::equal_to> && | |||
(forward_range<Rng> || detail::tiny_range<Pattern>)) | |||
{ | |||
return views::split(rng, static_cast<Pattern &&>(pattern)) | | |||
views::transform(to<split_value_t<Rng>>()) | to_vector; | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates split_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<split_fn>, split) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,81 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_SPLIT_WHEN_HPP | |||
#define RANGES_V3_ACTION_SPLIT_WHEN_HPP | |||
#include <vector> | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/concepts.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/conversion.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
#include <range/v3/view/split_when.hpp> | |||
#include <range/v3/view/transform.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct split_when_fn | |||
{ | |||
private: | |||
template<typename Rng> | |||
using split_value_t = meta::if_c<(bool)ranges::container<Rng>, uncvref_t<Rng>, | |||
std::vector<range_value_t<Rng>>>; | |||
public: | |||
// BUGBUG something is not right with the actions. It should be possible | |||
// to move a container into a split and have elements moved into the result. | |||
template<typename Rng, typename Fun> | |||
auto operator()(Rng && rng, Fun fun) const // | |||
-> CPP_ret(std::vector<split_value_t<Rng>>)( // | |||
requires forward_range<Rng> && // | |||
invocable<Fun &, iterator_t<Rng>, sentinel_t<Rng>> && invocable< | |||
Fun &, iterator_t<Rng>, iterator_t<Rng>> && | |||
copy_constructible<Fun> && convertible_to< | |||
invoke_result_t<Fun &, iterator_t<Rng>, sentinel_t<Rng>>, | |||
std::pair<bool, iterator_t<Rng>>>) | |||
{ | |||
return views::split_when(rng, std::move(fun)) | | |||
views::transform(to<split_value_t<Rng>>()) | to_vector; | |||
} | |||
template<typename Rng, typename Fun> | |||
auto operator()(Rng && rng, Fun fun) const | |||
-> CPP_ret(std::vector<split_value_t<Rng>>)( // | |||
requires forward_range<Rng> && predicate< | |||
Fun const &, range_reference_t<Rng>> && copy_constructible<Fun>) | |||
{ | |||
return views::split_when(rng, std::move(fun)) | | |||
views::transform(to<split_value_t<Rng>>()) | to_vector; | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates split_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<split_when_fn>, split_when) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,65 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_STABLE_SORT_HPP | |||
#define RANGES_V3_ACTION_STABLE_SORT_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/algorithm/stable_sort.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct stable_sort_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename C, typename P = identity> | |||
static auto CPP_fun(bind)(stable_sort_fn stable_sort, C pred, | |||
P proj = P{})( // | |||
requires(!range<C>)) | |||
{ | |||
return bind_back(stable_sort, std::move(pred), std::move(proj)); | |||
} | |||
public: | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto operator()(Rng && rng, C pred = C{}, P proj = P{}) const | |||
-> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||
{ | |||
ranges::stable_sort(rng, std::move(pred), std::move(proj)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates stable_sort_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<stable_sort_fn>, stable_sort) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,81 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_STRIDE_HPP | |||
#define RANGES_V3_ACTION_STRIDE_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct stride_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename D> | |||
static auto CPP_fun(bind)(stride_fn stride, D step)( // | |||
requires integral<D>) | |||
{ | |||
return bind_back(stride, step); | |||
} | |||
public: | |||
template<typename Rng, typename D = range_difference_t<Rng>> | |||
auto operator()(Rng && rng, range_difference_t<Rng> const step) const | |||
-> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && | |||
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> && | |||
permutable<iterator_t<Rng>>) | |||
{ | |||
using I = iterator_t<Rng>; | |||
using S = sentinel_t<Rng>; | |||
RANGES_EXPECT(0 < step); | |||
if(1 < step) | |||
{ | |||
I first = ranges::begin(rng); | |||
S const last = ranges::end(rng); | |||
if(first != last) | |||
{ | |||
for(I i = ranges::next(++first, step - 1, last); i != last; | |||
advance(i, step, last), ++first) | |||
{ | |||
*first = iter_move(i); | |||
} | |||
} | |||
ranges::actions::erase(rng, first, last); | |||
} | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates stride_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<stride_fn>, stride) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,66 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_TAKE_HPP | |||
#define RANGES_V3_ACTION_TAKE_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct take_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename Int> | |||
static auto CPP_fun(bind)(take_fn take, Int n)( // | |||
requires integral<Int>) | |||
{ | |||
return bind_back(take, n); | |||
} | |||
public: | |||
template<typename Rng> | |||
auto operator()(Rng && rng, range_difference_t<Rng> n) const | |||
-> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && | |||
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>>) | |||
{ | |||
RANGES_EXPECT(n >= 0); | |||
ranges::actions::erase( | |||
rng, ranges::next(begin(rng), n, end(rng)), end(rng)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates take_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<take_fn>, take) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,65 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_TAKE_WHILE_HPP | |||
#define RANGES_V3_ACTION_TAKE_WHILE_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/algorithm/find_if_not.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct take_while_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename Fun> | |||
static auto CPP_fun(bind)(take_while_fn take_while, Fun fun)( // | |||
requires(!range<Fun>)) | |||
{ | |||
return bind_back(take_while, std::move(fun)); | |||
} | |||
public: | |||
template<typename Rng, typename Fun> | |||
auto operator()(Rng && rng, Fun fun) const -> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && | |||
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> && | |||
indirect_unary_predicate<Fun, iterator_t<Rng>>) | |||
{ | |||
ranges::actions::erase( | |||
rng, find_if_not(begin(rng), end(rng), std::move(fun)), end(rng)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates take_while_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<take_while_fn>, take_while) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,64 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_TRANSFORM_HPP | |||
#define RANGES_V3_ACTION_TRANSFORM_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/algorithm/transform.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct transform_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename F, typename P = identity> | |||
static auto CPP_fun(bind)(transform_fn transform, F fun, P proj = P{})( // | |||
requires(!range<F>)) | |||
{ | |||
return bind_back(transform, std::move(fun), std::move(proj)); | |||
} | |||
public: | |||
template<typename Rng, typename F, typename P = identity> | |||
auto operator()(Rng && rng, F fun, P proj = P{}) const -> CPP_ret(Rng)( // | |||
requires input_range<Rng> && copy_constructible<F> && | |||
writable<iterator_t<Rng>, | |||
indirect_result_t<F &, projected<iterator_t<Rng>, P>>>) | |||
{ | |||
ranges::transform(rng, begin(rng), std::move(fun), std::move(proj)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates transform_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<transform_fn>, transform) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,68 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_UNIQUE_HPP | |||
#define RANGES_V3_ACTION_UNIQUE_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/algorithm/unique.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct unique_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename C, typename P = identity> | |||
static auto CPP_fun(bind)(unique_fn unique, C pred, P proj = P{})( // | |||
requires(!range<C>)) | |||
{ | |||
return bind_back(unique, std::move(pred), std::move(proj)); | |||
} | |||
public: | |||
template<typename Rng, typename C = equal_to, typename P = identity> | |||
auto operator()(Rng && rng, C pred = C{}, P proj = P{}) const | |||
-> CPP_ret(Rng)( // | |||
requires forward_range<Rng> && | |||
erasable_range<Rng &, iterator_t<Rng>, sentinel_t<Rng>> && | |||
sortable<iterator_t<Rng>, C, P>) | |||
{ | |||
auto it = ranges::unique(rng, std::move(pred), std::move(proj)); | |||
ranges::erase(rng, it, end(rng)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \relates unique_fn | |||
/// \sa action | |||
RANGES_INLINE_VARIABLE(action<unique_fn>, unique) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif |
@@ -0,0 +1,74 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Andrey Diduh 2019 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ACTION_UNSTABLE_REMOVE_IF_HPP | |||
#define RANGES_V3_ACTION_UNSTABLE_REMOVE_IF_HPP | |||
#include <utility> | |||
#include <concepts/concepts.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/action/action.hpp> | |||
#include <range/v3/action/erase.hpp> | |||
#include <range/v3/algorithm/unstable_remove_if.hpp> | |||
#include <range/v3/functional/bind_back.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-actions | |||
/// @{ | |||
namespace actions | |||
{ | |||
struct unstable_remove_if_fn | |||
{ | |||
private: | |||
friend action_access; | |||
template<typename C, typename P = identity> | |||
static auto CPP_fun(bind)(unstable_remove_if_fn unstable_remove_if, C pred, | |||
P proj = P{})( // | |||
requires(!range<C>)) | |||
{ | |||
return bind_back(unstable_remove_if, std::move(pred), std::move(proj)); | |||
} | |||
public: | |||
template<typename Rng, typename C, typename P = identity> | |||
auto operator()(Rng && rng, C pred, P proj = P{}) const -> CPP_ret(Rng)( // | |||
requires bidirectional_range<Rng> && common_range<Rng> && | |||
permutable<iterator_t<Rng>> && | |||
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>> && | |||
erasable_range<Rng, iterator_t<Rng>, iterator_t<Rng>>) | |||
{ | |||
auto it = ranges::unstable_remove_if(ranges::begin(rng), | |||
ranges::end(rng), | |||
std::move(pred), | |||
std::move(proj)); | |||
ranges::erase(rng, it, ranges::end(rng)); | |||
return static_cast<Rng &&>(rng); | |||
} | |||
}; | |||
/// \ingroup group-actions | |||
/// \sa `action` | |||
/// \sa `actions::unstable_remove_if_fn` | |||
RANGES_INLINE_VARIABLE(action<unstable_remove_if_fn>, unstable_remove_if) | |||
} // namespace actions | |||
/// @} | |||
} // namespace ranges | |||
#endif // RANGES_V3_ACTION_UNSTABLE_REMOVE_IF_HPP |
@@ -0,0 +1,108 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_HPP | |||
#define RANGES_V3_ALGORITHM_HPP | |||
#include <range/v3/detail/config.hpp> | |||
RANGES_DISABLE_WARNINGS | |||
#include <range/v3/algorithm/adjacent_find.hpp> | |||
#include <range/v3/algorithm/adjacent_remove_if.hpp> | |||
#include <range/v3/algorithm/all_of.hpp> | |||
#include <range/v3/algorithm/any_of.hpp> | |||
#include <range/v3/algorithm/binary_search.hpp> | |||
#include <range/v3/algorithm/copy.hpp> | |||
#include <range/v3/algorithm/copy_backward.hpp> | |||
#include <range/v3/algorithm/copy_if.hpp> | |||
#include <range/v3/algorithm/copy_n.hpp> | |||
#include <range/v3/algorithm/count.hpp> | |||
#include <range/v3/algorithm/count_if.hpp> | |||
#include <range/v3/algorithm/ends_with.hpp> | |||
#include <range/v3/algorithm/equal.hpp> | |||
#include <range/v3/algorithm/equal_range.hpp> | |||
#include <range/v3/algorithm/fill.hpp> | |||
#include <range/v3/algorithm/fill_n.hpp> | |||
#include <range/v3/algorithm/find.hpp> | |||
#include <range/v3/algorithm/find_end.hpp> | |||
#include <range/v3/algorithm/find_first_of.hpp> | |||
#include <range/v3/algorithm/find_if.hpp> | |||
#include <range/v3/algorithm/find_if_not.hpp> | |||
#include <range/v3/algorithm/for_each.hpp> | |||
#include <range/v3/algorithm/for_each_n.hpp> | |||
#include <range/v3/algorithm/generate.hpp> | |||
#include <range/v3/algorithm/generate_n.hpp> | |||
#include <range/v3/algorithm/heap_algorithm.hpp> | |||
#include <range/v3/algorithm/inplace_merge.hpp> | |||
#include <range/v3/algorithm/is_partitioned.hpp> | |||
#include <range/v3/algorithm/is_sorted.hpp> | |||
#include <range/v3/algorithm/is_sorted_until.hpp> | |||
#include <range/v3/algorithm/lexicographical_compare.hpp> | |||
#include <range/v3/algorithm/lower_bound.hpp> | |||
#include <range/v3/algorithm/max.hpp> | |||
#include <range/v3/algorithm/max_element.hpp> | |||
#include <range/v3/algorithm/merge.hpp> | |||
#include <range/v3/algorithm/min.hpp> | |||
#include <range/v3/algorithm/min_element.hpp> | |||
#include <range/v3/algorithm/minmax.hpp> | |||
#include <range/v3/algorithm/minmax_element.hpp> | |||
#include <range/v3/algorithm/mismatch.hpp> | |||
#include <range/v3/algorithm/move.hpp> | |||
#include <range/v3/algorithm/move_backward.hpp> | |||
#include <range/v3/algorithm/none_of.hpp> | |||
#include <range/v3/algorithm/nth_element.hpp> | |||
#include <range/v3/algorithm/partial_sort.hpp> | |||
#include <range/v3/algorithm/partial_sort_copy.hpp> | |||
#include <range/v3/algorithm/partition.hpp> | |||
#include <range/v3/algorithm/partition_copy.hpp> | |||
#include <range/v3/algorithm/partition_point.hpp> | |||
#include <range/v3/algorithm/permutation.hpp> | |||
#include <range/v3/algorithm/remove.hpp> | |||
#include <range/v3/algorithm/remove_copy.hpp> | |||
#include <range/v3/algorithm/remove_copy_if.hpp> | |||
#include <range/v3/algorithm/remove_if.hpp> | |||
#include <range/v3/algorithm/replace.hpp> | |||
#include <range/v3/algorithm/replace_copy.hpp> | |||
#include <range/v3/algorithm/replace_copy_if.hpp> | |||
#include <range/v3/algorithm/replace_if.hpp> | |||
#include <range/v3/algorithm/reverse.hpp> | |||
#include <range/v3/algorithm/reverse_copy.hpp> | |||
#include <range/v3/algorithm/rotate.hpp> | |||
#include <range/v3/algorithm/rotate_copy.hpp> | |||
#include <range/v3/algorithm/sample.hpp> | |||
#include <range/v3/algorithm/search.hpp> | |||
#include <range/v3/algorithm/search_n.hpp> | |||
#include <range/v3/algorithm/set_algorithm.hpp> | |||
#include <range/v3/algorithm/shuffle.hpp> | |||
#include <range/v3/algorithm/sort.hpp> | |||
#include <range/v3/algorithm/stable_partition.hpp> | |||
#include <range/v3/algorithm/stable_sort.hpp> | |||
#include <range/v3/algorithm/starts_with.hpp> | |||
#include <range/v3/algorithm/swap_ranges.hpp> | |||
#include <range/v3/algorithm/transform.hpp> | |||
#include <range/v3/algorithm/unique.hpp> | |||
#include <range/v3/algorithm/unique_copy.hpp> | |||
#include <range/v3/algorithm/unstable_remove_if.hpp> | |||
#include <range/v3/algorithm/upper_bound.hpp> | |||
// BUGBUG | |||
#include <range/v3/algorithm/aux_/equal_range_n.hpp> | |||
#include <range/v3/algorithm/aux_/lower_bound_n.hpp> | |||
#include <range/v3/algorithm/aux_/merge_n.hpp> | |||
#include <range/v3/algorithm/aux_/merge_n_with_buffer.hpp> | |||
#include <range/v3/algorithm/aux_/sort_n_with_buffer.hpp> | |||
#include <range/v3/algorithm/aux_/upper_bound_n.hpp> | |||
RANGES_RE_ENABLE_WARNINGS | |||
#endif |
@@ -0,0 +1,73 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_ADJACENT_FIND_HPP | |||
#define RANGES_V3_ALGORITHM_ADJACENT_FIND_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(adjacent_find) | |||
/// \brief function template \c adjacent_find | |||
/// | |||
/// range-based version of the \c adjacent_find std algorithm | |||
/// | |||
/// \pre `Rng` is a model of the `Range` concept | |||
/// \pre `C` is a model of the `BinaryPredicate` concept | |||
template<typename I, typename S, typename C = equal_to, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(adjacent_find)( | |||
I first, S last, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires forward_iterator<I> && sentinel_for<S, I> && | |||
indirect_relation<C, projected<I, P>>) | |||
{ | |||
if(first == last) | |||
return first; | |||
auto inext = first; | |||
for(; ++inext != last; first = inext) | |||
if(invoke(pred, invoke(proj, *first), invoke(proj, *inext))) | |||
return first; | |||
return inext; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = equal_to, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(adjacent_find)(Rng && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires forward_range<Rng> && | |||
indirect_relation<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(adjacent_find) | |||
namespace cpp20 | |||
{ | |||
using ranges::adjacent_find; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // RANGE_ALGORITHM_ADJACENT_FIND_HPP |
@@ -0,0 +1,91 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler | |||
// Copyright Christopher Di Bella | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP | |||
#define RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP | |||
#include <functional> | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/adjacent_find.hpp> | |||
#include <range/v3/algorithm/move.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/move.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(adjacent_remove_if) | |||
/// \brief function \c adjacent_remove_if | |||
/// | |||
/// range-based version of the \c adjacent_remove_if algorithm | |||
/// | |||
/// \pre `Rng` is a model of the `forward_range` concept. | |||
/// \pre `Pred` is a model of the `BinaryPredicate` concept. | |||
template<typename I, typename S, typename Pred, typename Proj = identity> | |||
auto RANGES_FUN_NIEBLOID(adjacent_remove_if)( | |||
I first, S last, Pred pred = {}, Proj proj = {}) | |||
->CPP_ret(I)( // | |||
requires permutable<I> && sentinel_for<S, I> && | |||
indirect_relation<Pred, projected<I, Proj>>) | |||
{ | |||
first = adjacent_find(std::move(first), last, std::ref(pred), std::ref(proj)); | |||
if(first == last) | |||
return first; | |||
auto i = first; | |||
for(auto j = ++i; ++j != last; ++i) | |||
{ | |||
if(!invoke(pred, invoke(proj, *i), invoke(proj, *j))) | |||
{ | |||
*first = iter_move(i); | |||
++first; | |||
} | |||
} | |||
*first = iter_move(i); | |||
++first; | |||
return first; | |||
} | |||
/// \overload | |||
template<typename Rng, typename Pred, typename Proj = identity> | |||
auto RANGES_FUN_NIEBLOID(adjacent_remove_if)( | |||
Rng && rng, Pred pred, Proj proj = {}) // | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires forward_range<Rng> && | |||
indirect_relation<Pred, projected<iterator_t<Rng>, Proj>> && | |||
permutable<iterator_t<Rng>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(adjacent_remove_if) | |||
namespace cpp20 | |||
{ | |||
using ranges::adjacent_remove_if; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // RANGES_V3_ALGORITHM_ADJACENT_REMOVE_IF_HPP |
@@ -0,0 +1,67 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Andrew Sutton 2014 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_ALL_OF_HPP | |||
#define RANGES_V3_ALGORITHM_ALL_OF_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(all_of) | |||
/// \brief function template \c all_of | |||
template<typename I, typename S, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(all_of)(I first, S last, F pred, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
indirect_unary_predicate<F, projected<I, P>>) | |||
{ | |||
for(; first != last; ++first) | |||
if(!invoke(pred, invoke(proj, *first))) | |||
break; | |||
return first == last; | |||
} | |||
/// \overload | |||
template<typename Rng, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(all_of)(Rng && rng, F pred, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires input_range<Rng> && | |||
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(all_of) | |||
namespace cpp20 | |||
{ | |||
using ranges::all_of; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,68 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Andrew Sutton 2014 | |||
// Copyright Gonzalo Brito Gadeschi 2014 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_ANY_OF_HPP | |||
#define RANGES_V3_ALGORITHM_ANY_OF_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(any_of) | |||
/// \brief function template \c any_of | |||
template<typename I, typename S, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(any_of)(I first, S last, F pred, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
indirect_unary_predicate<F, projected<I, P>>) | |||
{ | |||
for(; first != last; ++first) | |||
if(invoke(pred, invoke(proj, *first))) | |||
return true; | |||
return false; | |||
} | |||
/// \overload | |||
template<typename Rng, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(any_of)(Rng && rng, F pred, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires input_range<Rng> && | |||
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(any_of) | |||
namespace cpp20 | |||
{ | |||
using ranges::any_of; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,84 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_AUX_EQUAL_RANGE_N_HPP | |||
#define RANGES_V3_ALGORITHM_AUX_EQUAL_RANGE_N_HPP | |||
#include <functional> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/aux_/lower_bound_n.hpp> | |||
#include <range/v3/algorithm/aux_/upper_bound_n.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
#include <range/v3/view/subrange.hpp> | |||
namespace ranges | |||
{ | |||
namespace aux | |||
{ | |||
struct equal_range_n_fn | |||
{ | |||
template<typename I, typename V, typename R = less, typename P = identity> | |||
auto operator()(I first, iter_difference_t<I> dist, V const & val, | |||
R pred = R{}, P proj = P{}) const -> CPP_ret(subrange<I>)( // | |||
requires forward_iterator<I> && | |||
indirect_strict_weak_order<R, V const *, projected<I, P>>) | |||
{ | |||
if(0 < dist) | |||
{ | |||
do | |||
{ | |||
auto half = dist / 2; | |||
auto middle = ranges::next(first, half); | |||
auto && v = *middle; | |||
auto && pv = invoke(proj, (decltype(v) &&)v); | |||
if(invoke(pred, pv, val)) | |||
{ | |||
first = std::move(++middle); | |||
dist -= half + 1; | |||
} | |||
else if(invoke(pred, val, pv)) | |||
{ | |||
dist = half; | |||
} | |||
else | |||
{ | |||
return {lower_bound_n(std::move(first), | |||
half, | |||
val, | |||
std::ref(pred), | |||
std::ref(proj)), | |||
upper_bound_n(ranges::next(middle), | |||
dist - (half + 1), | |||
val, | |||
std::ref(pred), | |||
std::ref(proj))}; | |||
} | |||
} while(0 != dist); | |||
} | |||
return {first, first}; | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(equal_range_n_fn, equal_range_n) | |||
} // namespace aux | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,75 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// Copyright Casey Carter 2016 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_AUX_LOWER_BOUND_N_HPP | |||
#define RANGES_V3_ALGORITHM_AUX_LOWER_BOUND_N_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/aux_/partition_point_n.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \cond | |||
namespace detail | |||
{ | |||
// [&](auto&& i){ return invoke(pred, i, val); } | |||
template<typename Pred, typename Val> | |||
struct lower_bound_predicate | |||
{ | |||
Pred & pred_; | |||
Val & val_; | |||
template<typename T> | |||
bool operator()(T && t) const | |||
{ | |||
return invoke(pred_, static_cast<T &&>(t), val_); | |||
} | |||
}; | |||
template<typename Pred, typename Val> | |||
lower_bound_predicate<Pred, Val> make_lower_bound_predicate(Pred & pred, | |||
Val & val) | |||
{ | |||
return {pred, val}; | |||
} | |||
} // namespace detail | |||
/// \endcond | |||
namespace aux | |||
{ | |||
struct lower_bound_n_fn | |||
{ | |||
template<typename I, typename V, typename C = less, typename P = identity> | |||
auto operator()(I first, iter_difference_t<I> d, V const & val, C pred = C{}, | |||
P proj = P{}) const -> CPP_ret(I)( // | |||
requires forward_iterator<I> && | |||
indirect_strict_weak_order<C, V const *, projected<I, P>>) | |||
{ | |||
return partition_point_n(std::move(first), | |||
d, | |||
detail::make_lower_bound_predicate(pred, val), | |||
std::move(proj)); | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(lower_bound_n_fn, lower_bound_n) | |||
} // namespace aux | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,106 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
// Copyright (c) 2009 Alexander Stepanov and Paul McJones | |||
// | |||
// Permission to use, copy, modify, distribute and sell this software | |||
// and its documentation for any purpose is hereby granted without | |||
// fee, provided that the above copyright notice appear in all copies | |||
// and that both that copyright notice and this permission notice | |||
// appear in supporting documentation. The authors make no | |||
// representations about the suitability of this software for any | |||
// purpose. It is provided "as is" without express or implied | |||
// warranty. | |||
// | |||
// Algorithms from | |||
// Elements of Programming | |||
// by Alexander Stepanov and Paul McJones | |||
// Addison-Wesley Professional, 2009 | |||
#ifndef RANGES_V3_ALGORITHM_AUX_MERGE_N_HPP | |||
#define RANGES_V3_ALGORITHM_AUX_MERGE_N_HPP | |||
#include <tuple> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/copy_n.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
namespace aux | |||
{ | |||
template<typename I0, typename I1, typename O> | |||
using merge_n_result = detail::in1_in2_out_result<I0, I1, O>; | |||
struct merge_n_fn | |||
{ | |||
template<typename I0, typename I1, typename O, typename C = less, | |||
typename P0 = identity, typename P1 = identity> | |||
auto operator()(I0 begin0, iter_difference_t<I0> n0, I1 begin1, | |||
iter_difference_t<I1> n1, O out, C r = C{}, P0 p0 = P0{}, | |||
P1 p1 = P1{}) const -> CPP_ret(merge_n_result<I0, I1, O>)( // | |||
requires mergeable<I0, I1, O, C, P0, P1>) | |||
{ | |||
using T = merge_n_result<I0, I1, O>; | |||
auto n0orig = n0; | |||
auto n1orig = n1; | |||
auto b0 = uncounted(begin0); | |||
auto b1 = uncounted(begin1); | |||
while(true) | |||
{ | |||
if(0 == n0) | |||
{ | |||
auto res = copy_n(b1, n1, out); | |||
begin0 = recounted(begin0, b0, n0orig); | |||
begin1 = recounted(begin1, res.in, n1orig); | |||
return T{begin0, begin1, res.out}; | |||
} | |||
if(0 == n1) | |||
{ | |||
auto res = copy_n(b0, n0, out); | |||
begin0 = recounted(begin0, res.in, n0orig); | |||
begin1 = recounted(begin1, b1, n1orig); | |||
return T{begin0, begin1, res.out}; | |||
} | |||
if(invoke(r, invoke(p1, *b1), invoke(p0, *b0))) | |||
{ | |||
*out = *b1; | |||
++b1; | |||
++out; | |||
--n1; | |||
} | |||
else | |||
{ | |||
*out = *b0; | |||
++b0; | |||
++out; | |||
--n0; | |||
} | |||
} | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(merge_n_fn, merge_n) | |||
} // namespace aux | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,66 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
// Copyright (c) 2009 Alexander Stepanov and Paul McJones | |||
// | |||
// Permission to use, copy, modify, distribute and sell this software | |||
// and its documentation for any purpose is hereby granted without | |||
// fee, provided that the above copyright notice appear in all copies | |||
// and that both that copyright notice and this permission notice | |||
// appear in supporting documentation. The authors make no | |||
// representations about the suitability of this software for any | |||
// purpose. It is provided "as is" without express or implied | |||
// warranty. | |||
// | |||
// Algorithms from | |||
// Elements of Programming | |||
// by Alexander Stepanov and Paul McJones | |||
// Addison-Wesley Professional, 2009 | |||
#ifndef RANGES_V3_ALGORITHM_AUX_MERGE_N_WITH_BUFFER_HPP | |||
#define RANGES_V3_ALGORITHM_AUX_MERGE_N_WITH_BUFFER_HPP | |||
#include <tuple> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/aux_/merge_n.hpp> | |||
#include <range/v3/algorithm/copy_n.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
namespace aux | |||
{ | |||
struct merge_n_with_buffer_fn | |||
{ | |||
template<typename I, typename B, typename C = less, typename P = identity> | |||
auto operator()(I begin0, iter_difference_t<I> n0, I begin1, | |||
iter_difference_t<I> n1, B buff, C r = C{}, P p = P{}) const | |||
-> CPP_ret(I)( // | |||
requires same_as<iter_common_reference_t<I>, | |||
iter_common_reference_t<B>> && | |||
indirectly_copyable<I, B> && mergeable<B, I, I, C, P, P>) | |||
{ | |||
copy_n(begin0, n0, buff); | |||
return merge_n(buff, n0, begin1, n1, begin0, r, p, p).out; | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(merge_n_with_buffer_fn, merge_n_with_buffer) | |||
} // namespace aux | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,60 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// Copyright Casey Carter 2016 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_AUX_PARTITION_POINT_N_HPP | |||
#define RANGES_V3_ALGORITHM_AUX_PARTITION_POINT_N_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
namespace aux | |||
{ | |||
struct partition_point_n_fn | |||
{ | |||
template<typename I, typename C, typename P = identity> | |||
auto operator()(I first, iter_difference_t<I> d, C pred, | |||
P proj = P{}) const // | |||
-> CPP_ret(I)( // | |||
requires forward_iterator<I> && | |||
indirect_unary_predicate<C, projected<I, P>>) | |||
{ | |||
if(0 < d) | |||
{ | |||
do | |||
{ | |||
auto half = d / 2; | |||
auto middle = next(uncounted(first), half); | |||
if(invoke(pred, invoke(proj, *middle))) | |||
{ | |||
first = recounted(first, std::move(++middle), half + 1); | |||
d -= half + 1; | |||
} | |||
else | |||
d = half; | |||
} while(0 != d); | |||
} | |||
return first; | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(partition_point_n_fn, partition_point_n) | |||
} // namespace aux | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,69 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
// Copyright (c) 2009 Alexander Stepanov and Paul McJones | |||
// | |||
// Permission to use, copy, modify, distribute and sell this software | |||
// and its documentation for any purpose is hereby granted without | |||
// fee, provided that the above copyright notice appear in all copies | |||
// and that both that copyright notice and this permission notice | |||
// appear in supporting documentation. The authors make no | |||
// representations about the suitability of this software for any | |||
// purpose. It is provided "as is" without express or implied | |||
// warranty. | |||
// | |||
// Algorithms from | |||
// Elements of Programming | |||
// by Alexander Stepanov and Paul McJones | |||
// Addison-Wesley Professional, 2009 | |||
#ifndef RANGES_V3_ALGORITHM_AUX_SORT_N_WITH_BUFFER_HPP | |||
#define RANGES_V3_ALGORITHM_AUX_SORT_N_WITH_BUFFER_HPP | |||
#include <tuple> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/aux_/merge_n_with_buffer.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
namespace aux | |||
{ | |||
struct sort_n_with_buffer_fn | |||
{ | |||
template<typename I, typename B, typename C = less, typename P = identity> | |||
auto operator()(I first, iter_difference_t<I> n, B buff, C r = C{}, | |||
P p = P{}) const -> CPP_ret(I)( // | |||
requires same_as<iter_common_reference_t<I>, | |||
iter_common_reference_t<B>> && | |||
indirectly_copyable<I, B> && mergeable<B, I, I, C, P, P>) | |||
{ | |||
auto half = n / 2; | |||
if(0 == half) | |||
return next(first, n); | |||
I m = (*this)(first, half, buff, r, p); | |||
(*this)(m, n - half, buff, r, p); | |||
return merge_n_with_buffer(first, half, m, n - half, buff, r, p); | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(sort_n_with_buffer_fn, sort_n_with_buffer) | |||
} // namespace aux | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,80 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// Copyright Casey Carter 2016 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_AUX_UPPER_BOUND_N_HPP | |||
#define RANGES_V3_ALGORITHM_AUX_UPPER_BOUND_N_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/aux_/partition_point_n.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \cond | |||
namespace detail | |||
{ | |||
// [&](auto&& i){ return !invoke(pred, val, i); } | |||
template<typename Pred, typename Val> | |||
struct upper_bound_predicate | |||
{ | |||
Pred * pred_; | |||
Val * val_; | |||
template<typename T> | |||
bool operator()(T && t) const | |||
{ | |||
return !invoke(*pred_, *val_, static_cast<T &&>(t)); | |||
} | |||
}; | |||
template<typename Pred, typename Val> | |||
upper_bound_predicate<Pred, Val> make_upper_bound_predicate(Pred & pred, | |||
Val & val) | |||
{ | |||
return {&pred, &val}; | |||
} | |||
} // namespace detail | |||
/// \endcond | |||
namespace aux | |||
{ | |||
struct upper_bound_n_fn | |||
{ | |||
/// \brief template function upper_bound | |||
/// | |||
/// range-based version of the `upper_bound` std algorithm | |||
/// | |||
/// \pre `Rng` is a model of the `Range` concept | |||
template<typename I, typename V, typename C = less, typename P = identity> | |||
auto operator()(I first, iter_difference_t<I> d, V const & val, C pred = C{}, | |||
P proj = P{}) const -> CPP_ret(I)( // | |||
requires forward_iterator<I> && | |||
indirect_strict_weak_order<C, V const *, projected<I, P>>) | |||
{ | |||
return partition_point_n(std::move(first), | |||
d, | |||
detail::make_upper_bound_predicate(pred, val), | |||
std::move(proj)); | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(upper_bound_n_fn, upper_bound_n) | |||
} // namespace aux | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,79 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_BINARY_SEARCH_HPP | |||
#define RANGES_V3_ALGORITHM_BINARY_SEARCH_HPP | |||
#include <functional> | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/lower_bound.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(binary_search) | |||
/// \brief function template \c binary_search | |||
/// | |||
/// range-based version of the \c binary_search std algorithm | |||
/// | |||
/// \pre `Rng` is a model of the `Range` concept | |||
template<typename I, | |||
typename S, | |||
typename V, | |||
typename C = less, | |||
typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(binary_search)( | |||
I first, S last, V const & val, C pred = C{}, P proj = P{}) | |||
->CPP_ret(bool)( // | |||
requires forward_iterator<I> && sentinel_for<S, I> && | |||
indirect_strict_weak_order<C, V const *, projected<I, P>>) | |||
{ | |||
first = | |||
lower_bound(std::move(first), last, val, std::ref(pred), std::ref(proj)); | |||
return first != last && !invoke(pred, val, invoke(proj, *first)); | |||
} | |||
/// \overload | |||
template<typename Rng, typename V, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(binary_search)( | |||
Rng && rng, V const & val, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires forward_range<Rng> && | |||
indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>) | |||
{ | |||
static_assert(!is_infinite<Rng>::value, | |||
"Trying to binary search an infinite range"); | |||
return (*this)(begin(rng), end(rng), val, std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(binary_search) | |||
namespace cpp20 | |||
{ | |||
using ranges::binary_search; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,86 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_COPY_HPP | |||
#define RANGES_V3_ALGORITHM_COPY_HPP | |||
#include <functional> | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/copy.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename O> | |||
using copy_result = detail::in_out_result<I, O>; | |||
RANGES_HIDDEN_DETAIL(namespace _copy CPP_PP_LBRACE()) | |||
RANGES_BEGIN_NIEBLOID(copy) | |||
/// \brief function template \c copy | |||
template<typename I, typename S, typename O> | |||
constexpr auto RANGES_FUN_NIEBLOID(copy)(I first, S last, O out) // | |||
->CPP_ret(copy_result<I, O>)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
weakly_incrementable<O> && indirectly_copyable<I, O>) | |||
{ | |||
for(; first != last; ++first, ++out) | |||
*out = *first; | |||
return {first, out}; | |||
} // namespace ranges | |||
/// \overload | |||
template<typename Rng, typename O> | |||
constexpr auto RANGES_FUN_NIEBLOID(copy)(Rng && rng, O out) // | |||
->CPP_ret(copy_result<safe_iterator_t<Rng>, O>)( // | |||
requires input_range<Rng> && weakly_incrementable<O> && | |||
indirectly_copyable<iterator_t<Rng>, O>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(out)); | |||
} | |||
RANGES_END_NIEBLOID(copy) | |||
RANGES_HIDDEN_DETAIL(CPP_PP_RBRACE()) | |||
#ifndef RANGES_DOXYGEN_INVOKED | |||
struct copy_fn | |||
: aux::copy_fn | |||
, _copy::copy_fn | |||
{ | |||
using aux::copy_fn::operator(); | |||
using _copy::copy_fn::operator(); | |||
}; | |||
RANGES_INLINE_VARIABLE(copy_fn, copy) | |||
#endif | |||
namespace cpp20 | |||
{ | |||
using ranges::copy_result; | |||
using ranges::RANGES_HIDDEN_DETAIL(_copy::) copy; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,71 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_COPY_BACKWARD_HPP | |||
#define RANGES_V3_ALGORITHM_COPY_BACKWARD_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename O> | |||
using copy_backward_result = detail::in_out_result<I, O>; | |||
RANGES_BEGIN_NIEBLOID(copy_backward) | |||
/// \brief function template \c copy_backward | |||
template<typename I, typename S, typename O> | |||
auto RANGES_FUN_NIEBLOID(copy_backward)(I first, S end_, O out) | |||
->CPP_ret(copy_backward_result<I, O>)( // | |||
requires bidirectional_iterator<I> && sentinel_for<S, I> && | |||
bidirectional_iterator<O> && indirectly_copyable<I, O>) | |||
{ | |||
I i = ranges::next(first, end_), last = i; | |||
while(first != i) | |||
*--out = *--i; | |||
return {last, out}; | |||
} | |||
/// \overload | |||
template<typename Rng, typename O> | |||
auto RANGES_FUN_NIEBLOID(copy_backward)(Rng && rng, O out) | |||
->CPP_ret(copy_backward_result<safe_iterator_t<Rng>, O>)( // | |||
requires bidirectional_range<Rng> && bidirectional_iterator<O> && | |||
indirectly_copyable<iterator_t<Rng>, O>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(out)); | |||
} | |||
RANGES_END_NIEBLOID(copy_backward) | |||
namespace cpp20 | |||
{ | |||
using ranges::copy_backward; | |||
using ranges::copy_backward_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,83 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_COPY_IF_HPP | |||
#define RANGES_V3_ALGORITHM_COPY_IF_HPP | |||
#include <functional> | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename O> | |||
using copy_if_result = detail::in_out_result<I, O>; | |||
RANGES_BEGIN_NIEBLOID(copy_if) | |||
/// \brief function template \c copy_if | |||
template<typename I, typename S, typename O, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(copy_if)(I first, S last, O out, F pred, P proj = P{}) // | |||
->CPP_ret(copy_if_result<I, O>)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
weakly_incrementable<O> && indirect_unary_predicate<F, projected<I, P>> && | |||
indirectly_copyable<I, O>) | |||
{ | |||
for(; first != last; ++first) | |||
{ | |||
auto && x = *first; | |||
if(invoke(pred, invoke(proj, x))) | |||
{ | |||
*out = (decltype(x) &&)x; | |||
++out; | |||
} | |||
} | |||
return {first, out}; | |||
} | |||
/// \overload | |||
template<typename Rng, typename O, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(copy_if)(Rng && rng, O out, F pred, P proj = P{}) | |||
->CPP_ret(copy_if_result<safe_iterator_t<Rng>, O>)( // | |||
requires input_range<Rng> && weakly_incrementable<O> && | |||
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>> && | |||
indirectly_copyable<iterator_t<Rng>, O>) | |||
{ | |||
return (*this)( | |||
begin(rng), end(rng), std::move(out), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(copy_if) | |||
namespace cpp20 | |||
{ | |||
using ranges::copy_if; | |||
using ranges::copy_if_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,66 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_COPY_N_HPP | |||
#define RANGES_V3_ALGORITHM_COPY_N_HPP | |||
#include <functional> | |||
#include <tuple> | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename O> | |||
using copy_n_result = detail::in_out_result<I, O>; | |||
RANGES_BEGIN_NIEBLOID(copy_n) | |||
/// \brief function template \c copy_n | |||
template<typename I, typename O, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(copy_n)(I first, iter_difference_t<I> n, O out) | |||
->CPP_ret(copy_n_result<I, O>)( // | |||
requires input_iterator<I> && weakly_incrementable<O> && | |||
indirectly_copyable<I, O>) | |||
{ | |||
RANGES_EXPECT(0 <= n); | |||
auto norig = n; | |||
auto b = uncounted(first); | |||
for(; n != 0; ++b, ++out, --n) | |||
*out = *b; | |||
return {recounted(first, b, norig), out}; | |||
} | |||
RANGES_END_NIEBLOID(copy_n) | |||
namespace cpp20 | |||
{ | |||
using ranges::copy_n; | |||
using ranges::copy_n_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,68 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_COUNT_HPP | |||
#define RANGES_V3_ALGORITHM_COUNT_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(count) | |||
/// \brief function template \c count | |||
template<typename I, typename S, typename V, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(count)(I first, S last, V const & val, P proj = P{}) | |||
->CPP_ret(iter_difference_t<I>)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
indirect_relation<equal_to, projected<I, P>, V const *>) | |||
{ | |||
iter_difference_t<I> n = 0; | |||
for(; first != last; ++first) | |||
if(invoke(proj, *first) == val) | |||
++n; | |||
return n; | |||
} | |||
/// \overload | |||
template<typename Rng, typename V, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(count)(Rng && rng, V const & val, P proj = P{}) | |||
->CPP_ret(iter_difference_t<iterator_t<Rng>>)( // | |||
requires input_range<Rng> && | |||
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, V const *>) | |||
{ | |||
return (*this)(begin(rng), end(rng), val, std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(count) | |||
namespace cpp20 | |||
{ | |||
using ranges::count; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,68 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_COUNT_IF_HPP | |||
#define RANGES_V3_ALGORITHM_COUNT_IF_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(count_if) | |||
/// \brief function template \c count_if | |||
template<typename I, typename S, typename R, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(count_if)(I first, S last, R pred, P proj = P{}) | |||
->CPP_ret(iter_difference_t<I>)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
indirect_unary_predicate<R, projected<I, P>>) | |||
{ | |||
iter_difference_t<I> n = 0; | |||
for(; first != last; ++first) | |||
if(invoke(pred, invoke(proj, *first))) | |||
++n; | |||
return n; | |||
} | |||
/// \overload | |||
template<typename Rng, typename R, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(count_if)(Rng && rng, R pred, P proj = P{}) | |||
->CPP_ret(iter_difference_t<iterator_t<Rng>>)( // | |||
requires input_range<Rng> && | |||
indirect_unary_predicate<R, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(count_if) | |||
namespace cpp20 | |||
{ | |||
using ranges::count_if; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,99 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Johel Guerrero 2019 | |||
// | |||
// Use, modification and distribution is subject to the | |||
// Boost Software License, Version 0.0. (See accompanying | |||
// file LICENSE_0_0.txt or copy at | |||
// http://www.boost.org/LICENSE_0_0.txt) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_ENDS_WITH_HPP | |||
#define RANGES_V3_ALGORITHM_ENDS_WITH_HPP | |||
#include <utility> | |||
#include <concepts/concepts.hpp> | |||
#include <range/v3/algorithm/equal.hpp> | |||
#include <range/v3/detail/config.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(ends_with) | |||
/// \brief function template \c ends_with | |||
template<typename I0, | |||
typename S0, | |||
typename I1, | |||
typename S1, | |||
typename C = equal_to, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(ends_with)(I0 begin0, | |||
S0 end0, | |||
I1 begin1, | |||
S1 end1, | |||
C pred = C{}, | |||
P0 proj0 = P0{}, | |||
P1 proj1 = P1{}) // | |||
->CPP_ret(bool)( // | |||
requires((forward_iterator<I0> && sentinel_for<S0, I0>) || | |||
(input_iterator<I0> && sized_sentinel_for<S0, I0>)) && | |||
((forward_iterator<I1> && sentinel_for<S1, I1>) || | |||
(input_iterator<I1> && sized_sentinel_for<S1, I1>)) && | |||
indirectly_comparable<I0, I1, C, P0, P1>) | |||
{ | |||
const auto drop = distance(begin0, end0) - distance(begin1, end1); | |||
if(drop < 0) | |||
return false; | |||
return equal(next(std::move(begin0), drop), | |||
std::move(end0), | |||
std::move(begin1), | |||
std::move(end1), | |||
std::move(pred), | |||
std::move(proj0), | |||
std::move(proj1)); | |||
} | |||
/// \overload | |||
template<typename Rng0, | |||
typename Rng1, | |||
typename C = equal_to, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(ends_with)( | |||
Rng0 && rng0, Rng1 && rng1, C pred = C{}, P0 proj0 = P0{}, P1 proj1 = P1{}) // | |||
->CPP_ret(bool)( // | |||
requires(forward_range<Rng0> || | |||
(input_range<Rng0> && sized_range<Rng0>)) && | |||
(forward_range<Rng1> || (input_range<Rng1> && sized_range<Rng1>)) && | |||
indirectly_comparable<iterator_t<Rng0>, iterator_t<Rng1>, C, P0, P1>) | |||
{ | |||
const auto drop = distance(rng0) - distance(rng1); | |||
if(drop < 0) | |||
return false; | |||
return equal(next(begin(rng0), drop), | |||
end(rng0), | |||
begin(rng1), | |||
end(rng1), | |||
std::move(pred), | |||
std::move(proj0), | |||
std::move(proj1)); | |||
} | |||
RANGES_END_NIEBLOID(ends_with) | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,175 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to the | |||
// Boost Software License, Version 0.0. (See accompanying | |||
// file LICENSE_0_0.txt or copy at | |||
// http://www.boost.org/LICENSE_0_0.txt) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_EQUAL_HPP | |||
#define RANGES_V3_ALGORITHM_EQUAL_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
/// \cond | |||
namespace detail | |||
{ | |||
template<typename I0, typename S0, typename I1, typename S1, typename C, | |||
typename P0, typename P1> | |||
constexpr bool equal_nocheck(I0 begin0, S0 end0, I1 begin1, S1 end1, C pred, | |||
P0 proj0, P1 proj1) | |||
{ | |||
for(; begin0 != end0 && begin1 != end1; ++begin0, ++begin1) | |||
if(!invoke(pred, invoke(proj0, *begin0), invoke(proj1, *begin1))) | |||
return false; | |||
return begin0 == end0 && begin1 == end1; | |||
} | |||
} // namespace detail | |||
/// \endcond | |||
RANGES_BEGIN_NIEBLOID(equal) | |||
/// \brief function template \c equal | |||
template<typename I0, | |||
typename S0, | |||
typename I1, | |||
typename C = equal_to, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
RANGES_DEPRECATED( | |||
"Use the variant of ranges::equal that takes an upper bound for " | |||
"both sequences") | |||
constexpr auto RANGES_FUN_NIEBLOID(equal)(I0 begin0, | |||
S0 end0, | |||
I1 begin1, | |||
C pred = C{}, | |||
P0 proj0 = P0{}, | |||
P1 proj1 = P1{}) // | |||
->CPP_ret(bool)( // | |||
requires input_iterator<I0> && sentinel_for<S0, I0> && | |||
input_iterator<I1> && indirectly_comparable<I0, I1, C, P0, P1>) | |||
{ | |||
for(; begin0 != end0; ++begin0, ++begin1) | |||
if(!invoke(pred, invoke(proj0, *begin0), invoke(proj1, *begin1))) | |||
return false; | |||
return true; | |||
} | |||
/// \overload | |||
template<typename I0, | |||
typename S0, | |||
typename I1, | |||
typename S1, | |||
typename C = equal_to, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(equal)(I0 begin0, | |||
S0 end0, | |||
I1 begin1, | |||
S1 end1, | |||
C pred = C{}, | |||
P0 proj0 = P0{}, | |||
P1 proj1 = P1{}) // | |||
->CPP_ret(bool)( // | |||
requires input_iterator<I0> && sentinel_for<S0, I0> && | |||
input_iterator<I1> && sentinel_for<S1, I1> && | |||
indirectly_comparable<I0, I1, C, P0, P1>) | |||
{ | |||
if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S0, I0> && | |||
sized_sentinel_for<S1, I1>)) | |||
if(distance(begin0, end0) != distance(begin1, end1)) | |||
return false; | |||
return detail::equal_nocheck(std::move(begin0), | |||
std::move(end0), | |||
std::move(begin1), | |||
std::move(end1), | |||
std::move(pred), | |||
std::move(proj0), | |||
std::move(proj1)); | |||
} | |||
/// \overload | |||
template<typename Rng0, | |||
typename I1Ref, | |||
typename C = equal_to, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
RANGES_DEPRECATED( | |||
"Use the variant of ranges::equal that takes an upper bound for " | |||
"both sequences") | |||
constexpr auto RANGES_FUN_NIEBLOID(equal)(Rng0 && rng0, | |||
I1Ref && begin1, | |||
C pred = C{}, | |||
P0 proj0 = P0{}, | |||
P1 proj1 = P1{}) // | |||
->CPP_ret(bool)( // | |||
requires input_range<Rng0> && input_iterator<uncvref_t<I1Ref>> && | |||
indirectly_comparable<iterator_t<Rng0>, uncvref_t<I1Ref>, C, P0, P1>) | |||
{ | |||
RANGES_DIAGNOSTIC_PUSH | |||
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS | |||
return (*this)(begin(rng0), | |||
end(rng0), | |||
(I1Ref &&) begin1, | |||
std::move(pred), | |||
std::move(proj0), | |||
std::move(proj1)); | |||
RANGES_DIAGNOSTIC_POP | |||
} | |||
/// \overload | |||
template<typename Rng0, | |||
typename Rng1, | |||
typename C = equal_to, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(equal)( | |||
Rng0 && rng0, Rng1 && rng1, C pred = C{}, P0 proj0 = P0{}, P1 proj1 = P1{}) // | |||
->CPP_ret(bool)( // | |||
requires input_range<Rng0> && input_range<Rng1> && | |||
indirectly_comparable<iterator_t<Rng0>, iterator_t<Rng1>, C, P0, P1>) | |||
{ | |||
if(RANGES_CONSTEXPR_IF(sized_range<Rng0> && sized_range<Rng1>)) | |||
if(distance(rng0) != distance(rng1)) | |||
return false; | |||
return detail::equal_nocheck(begin(rng0), | |||
end(rng0), | |||
begin(rng1), | |||
end(rng1), | |||
std::move(pred), | |||
std::move(proj0), | |||
std::move(proj1)); | |||
} | |||
RANGES_END_NIEBLOID(equal) | |||
namespace cpp20 | |||
{ | |||
using ranges::equal; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,128 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// Copyright Casey Carter 2016 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_EQUAL_RANGE_HPP | |||
#define RANGES_V3_ALGORITHM_EQUAL_RANGE_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/aux_/equal_range_n.hpp> | |||
#include <range/v3/algorithm/aux_/lower_bound_n.hpp> | |||
#include <range/v3/algorithm/upper_bound.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
#include <range/v3/view/subrange.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(equal_range) | |||
/// \brief function template \c equal_range | |||
template<typename I, | |||
typename S, | |||
typename V, | |||
typename C = less, | |||
typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(equal_range)( | |||
I first, S last, V const & val, C pred = C{}, P proj = P{}) | |||
->CPP_ret(subrange<I>)( // | |||
requires forward_iterator<I> && sentinel_for<S, I> && | |||
indirect_strict_weak_order<C, V const *, projected<I, P>>) | |||
{ | |||
if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S, I>)) | |||
{ | |||
auto const len = distance(first, last); | |||
return aux::equal_range_n( | |||
std::move(first), len, val, std::move(pred), std::move(proj)); | |||
} | |||
// Probe exponentially for either end-of-range, an iterator that | |||
// is past the equal range (i.e., denotes an element greater | |||
// than val), or is in the equal range (denotes an element equal | |||
// to val). | |||
auto dist = iter_difference_t<I>{1}; | |||
while(true) | |||
{ | |||
auto mid = first; | |||
auto d = advance(mid, dist, last); | |||
if(d || mid == last) | |||
{ | |||
// at the end of the input range | |||
dist -= d; | |||
return aux::equal_range_n( | |||
std::move(first), dist, val, std::ref(pred), std::ref(proj)); | |||
} | |||
// if val < *mid, mid is after the target range. | |||
auto && v = *mid; | |||
auto && pv = invoke(proj, (decltype(v) &&)v); | |||
if(invoke(pred, val, pv)) | |||
{ | |||
return aux::equal_range_n( | |||
std::move(first), dist, val, std::ref(pred), std::ref(proj)); | |||
} | |||
else if(!invoke(pred, pv, val)) | |||
{ | |||
// *mid == val: the lower bound is <= mid, and the upper bound is > | |||
// mid. | |||
return { | |||
aux::lower_bound_n( | |||
std::move(first), dist, val, std::ref(pred), std::ref(proj)), | |||
upper_bound(std::move(mid), | |||
std::move(last), | |||
val, | |||
std::ref(pred), | |||
std::ref(proj))}; | |||
} | |||
// *mid < val, mid is before the target range. | |||
first = std::move(mid); | |||
++first; | |||
dist *= 2; | |||
} | |||
} | |||
/// \overload | |||
template<typename Rng, typename V, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(equal_range)( | |||
Rng && rng, V const & val, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(safe_subrange_t<Rng>)( // | |||
requires forward_range<Rng> && | |||
indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>) | |||
{ | |||
if(RANGES_CONSTEXPR_IF(sized_range<Rng>)) | |||
{ | |||
auto const len = distance(rng); | |||
return aux::equal_range_n( | |||
begin(rng), len, val, std::move(pred), std::move(proj)); | |||
} | |||
return (*this)(begin(rng), end(rng), val, std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(equal_range) | |||
namespace cpp20 | |||
{ | |||
using ranges::equal_range; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,60 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_FILL_HPP | |||
#define RANGES_V3_ALGORITHM_FILL_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(fill) | |||
/// \brief function template \c fill | |||
template<typename O, typename S, typename V> | |||
auto RANGES_FUN_NIEBLOID(fill)(O first, S last, V const & val) // | |||
->CPP_ret(O)( // | |||
requires output_iterator<O, V const &> && sentinel_for<S, O>) | |||
{ | |||
for(; first != last; ++first) | |||
*first = val; | |||
return first; | |||
} | |||
/// \overload | |||
template<typename Rng, typename V> | |||
auto RANGES_FUN_NIEBLOID(fill)(Rng && rng, V const & val) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires output_range<Rng, V const &>) | |||
{ | |||
return (*this)(begin(rng), end(rng), val); | |||
} | |||
RANGES_END_NIEBLOID(fill) | |||
namespace cpp20 | |||
{ | |||
using ranges::fill; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,56 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_FILL_N_HPP | |||
#define RANGES_V3_ALGORITHM_FILL_N_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(fill_n) | |||
/// \brief function template \c equal | |||
template<typename O, typename V> | |||
auto RANGES_FUN_NIEBLOID(fill_n)(O first, iter_difference_t<O> n, V const & val) | |||
->CPP_ret(O)( // | |||
requires output_iterator<O, V const &>) | |||
{ | |||
RANGES_EXPECT(n >= 0); | |||
auto norig = n; | |||
auto b = uncounted(first); | |||
for(; n != 0; ++b, --n) | |||
*b = val; | |||
return recounted(first, b, norig); | |||
} | |||
RANGES_END_NIEBLOID(fill_n) | |||
namespace cpp20 | |||
{ | |||
using ranges::fill_n; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,75 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_FIND_HPP | |||
#define RANGES_V3_ALGORITHM_FIND_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(find) | |||
/// \brief template function \c find | |||
/// | |||
/// range-based version of the \c find std algorithm | |||
/// | |||
/// \pre `Rng` is a model of the `Range` concept | |||
/// \pre `I` is a model of the `input_iterator` concept | |||
/// \pre `S` is a model of the `sentinel_for<I>` concept | |||
/// \pre `P` is a model of the `invocable<iter_common_reference_t<I>>` concept | |||
/// \pre The ResultType of `P` is equality_comparable with V | |||
template<typename I, typename S, typename V, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(find)(I first, S last, V const & val, P proj = P{}) | |||
->CPP_ret(I)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
indirect_relation<equal_to, projected<I, P>, V const *>) | |||
{ | |||
for(; first != last; ++first) | |||
if(invoke(proj, *first) == val) | |||
break; | |||
return first; | |||
} | |||
/// \overload | |||
template<typename Rng, typename V, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(find)(Rng && rng, V const & val, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires input_range<Rng> && | |||
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, V const *>) | |||
{ | |||
return (*this)(begin(rng), end(rng), val, std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(find) | |||
namespace cpp20 | |||
{ | |||
using ranges::find; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,236 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_FIND_END_HPP | |||
#define RANGES_V3_ALGORITHM_FIND_END_HPP | |||
#include <utility> | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
#include <range/v3/view/subrange.hpp> | |||
namespace ranges | |||
{ | |||
/// \cond | |||
namespace detail | |||
{ | |||
template<typename I, typename S> | |||
auto next_to_if(I i, S s, std::true_type) -> CPP_ret(I)( // | |||
requires input_iterator<I> && sentinel_for<S, I>) | |||
{ | |||
return ranges::next(i, s); | |||
} | |||
template<typename I, typename S> | |||
auto next_to_if(I, S s, std::false_type) -> CPP_ret(S)( // | |||
requires input_iterator<I> && sentinel_for<S, I>) | |||
{ | |||
return s; | |||
} | |||
template<bool B, typename I, typename S> | |||
auto next_to_if(I i, S s) -> CPP_ret(meta::if_c<B, I, S>)( // | |||
requires input_iterator<I> && sentinel_for<S, I>) | |||
{ | |||
return detail::next_to_if(std::move(i), std::move(s), meta::bool_<B>{}); | |||
} | |||
template<typename I1, typename S1, typename I2, typename S2, typename R, | |||
typename P> | |||
subrange<I1> find_end_impl(I1 begin1, S1 end1, I2 begin2, S2 end2, R pred, P proj, | |||
detail::forward_iterator_tag_, | |||
detail::forward_iterator_tag_) | |||
{ | |||
bool found = false; | |||
I1 res_begin, res_end; | |||
if(begin2 == end2) | |||
{ | |||
auto e1 = ranges::next(begin1, end1); | |||
return {e1, e1}; | |||
} | |||
while(true) | |||
{ | |||
while(true) | |||
{ | |||
if(begin1 == end1) | |||
return {(found ? res_begin : begin1), (found ? res_end : begin1)}; | |||
if(invoke(pred, invoke(proj, *begin1), *begin2)) | |||
break; | |||
++begin1; | |||
} | |||
auto tmp1 = begin1; | |||
auto tmp2 = begin2; | |||
while(true) | |||
{ | |||
if(++tmp2 == end2) | |||
{ | |||
res_begin = begin1++; | |||
res_end = ++tmp1; | |||
found = true; | |||
break; | |||
} | |||
if(++tmp1 == end1) | |||
return {(found ? res_begin : tmp1), (found ? res_end : tmp1)}; | |||
if(!invoke(pred, invoke(proj, *tmp1), *tmp2)) | |||
{ | |||
++begin1; | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
template<typename I1, typename I2, typename R, typename P> | |||
subrange<I1> find_end_impl(I1 begin1, I1 end1, I2 begin2, I2 end2, R pred, P proj, | |||
detail::bidirectional_iterator_tag_, | |||
detail::bidirectional_iterator_tag_) | |||
{ | |||
// modeled after search algorithm (in reverse) | |||
if(begin2 == end2) | |||
return {end1, end1}; // Everything matches an empty sequence | |||
I1 l1 = end1; | |||
I2 l2 = end2; | |||
--l2; | |||
while(true) | |||
{ | |||
// Find end element in sequence 1 that matches *(end2-1), with a mininum | |||
// of loop checks | |||
do | |||
// return {end1,end1} if no element matches *begin2 | |||
if(begin1 == l1) | |||
return {end1, end1}; | |||
while(!invoke(pred, invoke(proj, *--l1), *l2)); | |||
// *l1 matches *l2, now match elements before here | |||
I1 m1 = l1; | |||
I2 m2 = l2; | |||
do | |||
// If pattern exhausted, {m1,++l1} is the answer | |||
// (works for 1 element pattern) | |||
if(m2 == begin2) | |||
return {m1, ++l1}; | |||
// Otherwise if source exhausted, pattern not found | |||
else if(m1 == begin1) | |||
return {end1, end1}; | |||
// if there is a mismatch, restart with a new l1 | |||
// else there is a match, check next elements | |||
while(invoke(pred, invoke(proj, *--m1), *--m2)); | |||
} | |||
} | |||
template<typename I1, typename I2, typename R, typename P> | |||
subrange<I1> find_end_impl(I1 begin1, I1 end1, I2 begin2, I2 end2, R pred, P proj, | |||
detail::random_access_iterator_tag_, | |||
detail::random_access_iterator_tag_) | |||
{ | |||
// Take advantage of knowing source and pattern lengths. Stop short when | |||
// source is smaller than pattern | |||
auto len2 = end2 - begin2; | |||
if(len2 == 0) | |||
return {end1, end1}; | |||
auto len1 = end1 - begin1; | |||
if(len1 < len2) | |||
return {end1, end1}; | |||
I1 const start = | |||
begin1 + (len2 - 1); // End of pattern match can't go before here | |||
I1 l1 = end1; | |||
I2 l2 = end2; | |||
--l2; | |||
while(true) | |||
{ | |||
do | |||
if(start == l1) | |||
return {end1, end1}; | |||
while(!invoke(pred, invoke(proj, *--l1), *l2)); | |||
I1 m1 = l1; | |||
I2 m2 = l2; | |||
do | |||
if(m2 == begin2) | |||
return {m1, ++l1}; | |||
// no need to check range on m1 because s guarantees we have enough source | |||
while(invoke(pred, invoke(proj, *--m1), *--m2)); | |||
} | |||
} | |||
} // namespace detail | |||
/// \endcond | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(find_end) | |||
/// \brief function template \c find_end | |||
template<typename I1, | |||
typename S1, | |||
typename I2, | |||
typename S2, | |||
typename R = equal_to, | |||
typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(find_end)( | |||
I1 begin1, S1 end1, I2 begin2, S2 end2, R pred = R{}, P proj = P{}) // | |||
->CPP_ret(subrange<I1>)( // | |||
requires forward_iterator<I1> && sentinel_for<S1, I1> && | |||
forward_iterator<I2> && sentinel_for<S2, I2> && | |||
indirect_relation<R, projected<I1, P>, I2>) | |||
{ | |||
constexpr bool Bidi = | |||
bidirectional_iterator<I1> && bidirectional_iterator<I2>; | |||
return detail::find_end_impl(begin1, | |||
detail::next_to_if<Bidi>(begin1, end1), | |||
begin2, | |||
detail::next_to_if<Bidi>(begin2, end2), | |||
std::move(pred), | |||
std::move(proj), | |||
iterator_tag_of<I1>(), | |||
iterator_tag_of<I2>()); | |||
} | |||
/// \overload | |||
template<typename Rng1, | |||
typename Rng2, | |||
typename R = equal_to, | |||
typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(find_end)( | |||
Rng1 && rng1, Rng2 && rng2, R pred = R{}, P proj = P{}) // | |||
->CPP_ret(safe_subrange_t<Rng1>)( // | |||
requires forward_range<Rng1> && forward_range<Rng2> && | |||
indirect_relation<R, projected<iterator_t<Rng1>, P>, iterator_t<Rng2>>) | |||
{ | |||
return (*this)(begin(rng1), | |||
end(rng1), | |||
begin(rng2), | |||
end(rng2), | |||
std::move(pred), | |||
std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(find_end) | |||
namespace cpp20 | |||
{ | |||
using ranges::find_end; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,101 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to the | |||
// Boost Software License, Version 0.0. (See accompanying | |||
// file LICENSE_0_0.txt or copy at | |||
// http://www.boost.org/LICENSE_0_0.txt) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_FIND_FIRST_OF_HPP | |||
#define RANGES_V3_ALGORITHM_FIND_FIRST_OF_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(find_first_of) | |||
// Rationale: return I0 instead of pair<I0,I1> because find_first_of need | |||
// not actually compute the end of [I1,S0); therefore, it is not necessarily | |||
// losing information. E.g., if begin0 == end0, we can return begin0 immediately. | |||
// If we returned pair<I0,I1>, we would need to do an O(N) scan to find the | |||
// end position. | |||
/// \brief function template \c find_first_of | |||
template<typename I0, | |||
typename S0, | |||
typename I1, | |||
typename S1, | |||
typename R = equal_to, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(find_first_of)(I0 begin0, | |||
S0 end0, | |||
I1 begin1, | |||
S1 end1, | |||
R pred = R{}, | |||
P0 proj0 = P0{}, | |||
P1 proj1 = P1{}) // | |||
->CPP_ret(I0)( // | |||
requires input_iterator<I0> && sentinel_for<S0, I0> && | |||
forward_iterator<I1> && sentinel_for<S1, I1> && | |||
indirect_relation<R, projected<I0, P0>, projected<I1, P1>>) | |||
{ | |||
for(; begin0 != end0; ++begin0) | |||
for(auto tmp = begin1; tmp != end1; ++tmp) | |||
if(invoke(pred, invoke(proj0, *begin0), invoke(proj1, *tmp))) | |||
return begin0; | |||
return begin0; | |||
} | |||
/// \overload | |||
template<typename Rng0, | |||
typename Rng1, | |||
typename R = equal_to, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(find_first_of)( | |||
Rng0 && rng0, Rng1 && rng1, R pred = R{}, P0 proj0 = P0{}, P1 proj1 = P1{}) // | |||
->CPP_ret(safe_iterator_t<Rng0>)( // | |||
requires input_range<Rng0> && forward_range<Rng1> && | |||
indirect_relation<R, | |||
projected<iterator_t<Rng0>, P0>, | |||
projected<iterator_t<Rng1>, P1>>) | |||
{ | |||
return (*this)(begin(rng0), | |||
end(rng0), | |||
begin(rng1), | |||
end(rng1), | |||
std::move(pred), | |||
std::move(proj0), | |||
std::move(proj1)); | |||
} | |||
RANGES_END_NIEBLOID(find_first_of) | |||
namespace cpp20 | |||
{ | |||
using ranges::find_first_of; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,77 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_FIND_IF_HPP | |||
#define RANGES_V3_ALGORITHM_FIND_IF_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(find_if) | |||
/// \brief template function \c find | |||
/// | |||
/// range-based version of the \c find std algorithm | |||
/// | |||
/// \pre `Rng` is a model of the `Range` concept | |||
/// \pre `I` is a model of the `input_iterator` concept | |||
/// \pre `S` is a model of the `sentinel_for<I>` concept | |||
/// \pre `P` is a model of the `invocable<V>` concept, where `V` is the | |||
/// value type of I. | |||
/// \pre `F` models `predicate<X>`, where `X` is the result type | |||
/// of `invocable<P, V>` | |||
template<typename I, typename S, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(find_if)(I first, S last, F pred, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
indirect_unary_predicate<F, projected<I, P>>) | |||
{ | |||
for(; first != last; ++first) | |||
if(invoke(pred, invoke(proj, *first))) | |||
break; | |||
return first; | |||
} | |||
/// \overload | |||
template<typename Rng, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(find_if)(Rng && rng, F pred, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires input_range<Rng> && | |||
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(find_if) | |||
namespace cpp20 | |||
{ | |||
using ranges::find_if; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,77 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_FIND_IF_NOT_HPP | |||
#define RANGES_V3_ALGORITHM_FIND_IF_NOT_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(find_if_not) | |||
/// \brief template function \c find_if_not | |||
/// | |||
/// range-based version of the \c find_if_not std algorithm | |||
/// | |||
/// \pre `Rng` is a model of the `Range` concept | |||
/// \pre `I` is a model of the `input_iterator` concept | |||
/// \pre `S` is a model of the `sentinel_for<I>` concept | |||
/// \pre `P` is a model of the `invocable<V>` concept, where `V` is the | |||
/// value type of I. | |||
/// \pre `F` models `predicate<X>`, where `X` is the result type | |||
/// of `invocable<P, V>` | |||
template<typename I, typename S, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(find_if_not)(I first, S last, F pred, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
indirect_unary_predicate<F, projected<I, P>>) | |||
{ | |||
for(; first != last; ++first) | |||
if(!invoke(pred, invoke(proj, *first))) | |||
break; | |||
return first; | |||
} | |||
/// \overload | |||
template<typename Rng, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(find_if_not)(Rng && rng, F pred, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires input_range<Rng> && | |||
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(find_if_not) | |||
namespace cpp20 | |||
{ | |||
using ranges::find_if_not; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,75 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_FOR_EACH_HPP | |||
#define RANGES_V3_ALGORITHM_FOR_EACH_HPP | |||
#include <functional> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/functional/reference_wrapper.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename F> | |||
using for_each_result = detail::in_fun_result<I, F>; | |||
RANGES_BEGIN_NIEBLOID(for_each) | |||
/// \brief function template \c for_each | |||
template<typename I, typename S, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(for_each)(I first, S last, F fun, P proj = P{}) | |||
->CPP_ret(for_each_result<I, F>)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
indirectly_unary_invocable<F, projected<I, P>>) | |||
{ | |||
for(; first != last; ++first) | |||
{ | |||
invoke(fun, invoke(proj, *first)); | |||
} | |||
return {detail::move(first), detail::move(fun)}; | |||
} | |||
/// \overload | |||
template<typename Rng, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(for_each)(Rng && rng, F fun, P proj = P{}) | |||
->CPP_ret(for_each_result<safe_iterator_t<Rng>, F>)( // | |||
requires input_range<Rng> && | |||
indirectly_unary_invocable<F, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return {(*this)(begin(rng), end(rng), ref(fun), detail::move(proj)).in, | |||
detail::move(fun)}; | |||
} | |||
RANGES_END_NIEBLOID(for_each) | |||
namespace cpp20 | |||
{ | |||
using ranges::for_each; | |||
using ranges::for_each_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,77 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// Copyright Rostislav Khlebnikov 2017 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_FOR_EACH_N_HPP | |||
#define RANGES_V3_ALGORITHM_FOR_EACH_N_HPP | |||
#include <functional> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(for_each_n) | |||
/// \brief function template \c for_each_n | |||
template<typename I, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(for_each_n)( | |||
I first, iter_difference_t<I> n, F fun, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires input_iterator<I> && | |||
indirectly_unary_invocable<F, projected<I, P>>) | |||
{ | |||
RANGES_EXPECT(0 <= n); | |||
auto norig = n; | |||
auto b = uncounted(first); | |||
for(; 0 < n; ++b, --n) | |||
invoke(fun, invoke(proj, *b)); | |||
return recounted(first, b, norig); | |||
} | |||
/// \overload | |||
template<typename Rng, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(for_each_n)( | |||
Rng && rng, range_difference_t<Rng> n, F fun, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires input_range<Rng> && | |||
indirectly_unary_invocable<F, projected<iterator_t<Rng>, P>>) | |||
{ | |||
if(sized_range<Rng>) | |||
RANGES_EXPECT(n <= distance(rng)); | |||
return (*this)(begin(rng), n, detail::move(fun), detail::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(for_each_n) | |||
// Not yet! | |||
// namespace cpp20 | |||
// { | |||
// using ranges::for_each_n; | |||
// } | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,70 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_GENERATE_HPP | |||
#define RANGES_V3_ALGORITHM_GENERATE_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/functional/reference_wrapper.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename O, typename F> | |||
using generate_result = detail::out_fun_result<O, F>; | |||
RANGES_BEGIN_NIEBLOID(generate) | |||
/// \brief function template \c generate_n | |||
template<typename O, typename S, typename F> | |||
auto RANGES_FUN_NIEBLOID(generate)(O first, S last, F fun) // | |||
->CPP_ret(generate_result<O, F>)( // | |||
requires invocable<F &> && output_iterator<O, invoke_result_t<F &>> && | |||
sentinel_for<S, O>) | |||
{ | |||
for(; first != last; ++first) | |||
*first = invoke(fun); | |||
return {detail::move(first), detail::move(fun)}; | |||
} | |||
/// \overload | |||
template<typename Rng, typename F> | |||
auto RANGES_FUN_NIEBLOID(generate)(Rng && rng, F fun) | |||
->CPP_ret(generate_result<safe_iterator_t<Rng>, F>)( // | |||
requires invocable<F &> && output_range<Rng, invoke_result_t<F &>>) | |||
{ | |||
return {(*this)(begin(rng), end(rng), ref(fun)).out, detail::move(fun)}; | |||
} | |||
RANGES_END_NIEBLOID(generate) | |||
namespace cpp20 | |||
{ | |||
using ranges::generate; | |||
using ranges::generate_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,63 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_GENERATE_N_HPP | |||
#define RANGES_V3_ALGORITHM_GENERATE_N_HPP | |||
#include <tuple> | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename O, typename F> | |||
using generate_n_result = detail::out_fun_result<O, F>; | |||
RANGES_BEGIN_NIEBLOID(generate_n) | |||
/// \brief function template \c generate_n | |||
template<typename O, typename F> | |||
auto RANGES_FUN_NIEBLOID(generate_n)(O first, iter_difference_t<O> n, F fun) | |||
->CPP_ret(generate_n_result<O, F>)( // | |||
requires invocable<F &> && output_iterator<O, invoke_result_t<F &>>) | |||
{ | |||
RANGES_EXPECT(n >= 0); | |||
auto norig = n; | |||
auto b = uncounted(first); | |||
for(; 0 != n; ++b, --n) | |||
*b = invoke(fun); | |||
return {recounted(first, b, norig), detail::move(fun)}; | |||
} | |||
RANGES_END_NIEBLOID(generate_n) | |||
namespace cpp20 | |||
{ | |||
using ranges::generate_n; | |||
using ranges::generate_n_result; | |||
} // namespace cpp20 | |||
// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,430 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
//===----------------------------------------------------------------------===// | |||
// | |||
// The LLVM Compiler Infrastructure | |||
// | |||
// This file is dual licensed under the MIT and the University of Illinois Open | |||
// Source Licenses. See LICENSE.TXT for details. | |||
// | |||
//===----------------------------------------------------------------------===// | |||
#ifndef RANGES_V3_ALGORITHM_HEAP_ALGORITHM_HPP | |||
#define RANGES_V3_ALGORITHM_HEAP_ALGORITHM_HPP | |||
#include <functional> | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \cond | |||
namespace detail | |||
{ | |||
struct is_heap_until_n_fn | |||
{ | |||
template<typename I, typename C = less, typename P = identity> | |||
auto operator()(I const begin_, iter_difference_t<I> const n_, C pred = C{}, | |||
P proj = P{}) const -> CPP_ret(I)( // | |||
requires random_access_iterator<I> && | |||
indirect_strict_weak_order<C, projected<I, P>>) | |||
{ | |||
RANGES_EXPECT(0 <= n_); | |||
iter_difference_t<I> p = 0, c = 1; | |||
I pp = begin_; | |||
while(c < n_) | |||
{ | |||
I cp = begin_ + c; | |||
if(invoke(pred, invoke(proj, *pp), invoke(proj, *cp))) | |||
return cp; | |||
++c; | |||
++cp; | |||
if(c == n_ || invoke(pred, invoke(proj, *pp), invoke(proj, *cp))) | |||
return cp; | |||
++p; | |||
++pp; | |||
c = 2 * p + 1; | |||
} | |||
return begin_ + n_; | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(is_heap_until_n_fn, is_heap_until_n) | |||
struct is_heap_n_fn | |||
{ | |||
template<typename I, typename C = less, typename P = identity> | |||
auto operator()(I first, iter_difference_t<I> n, C pred = C{}, | |||
P proj = P{}) const -> CPP_ret(bool)( // | |||
requires random_access_iterator<I> && | |||
indirect_strict_weak_order<C, projected<I, P>>) | |||
{ | |||
return is_heap_until_n(first, n, std::move(pred), std::move(proj)) == | |||
first + n; | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(is_heap_n_fn, is_heap_n) | |||
} // namespace detail | |||
/// \endcond | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(is_heap_until) | |||
/// \brief function template \c is_heap_until | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(is_heap_until)( | |||
I first, S last, C pred = C{}, P proj = P{}) | |||
->CPP_ret(I)( // | |||
requires random_access_iterator<I> && sentinel_for<S, I> && | |||
indirect_strict_weak_order<C, projected<I, P>>) | |||
{ | |||
return detail::is_heap_until_n(std::move(first), | |||
distance(first, last), | |||
std::move(pred), | |||
std::move(proj)); | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(is_heap_until)(Rng && rng, C pred = C{}, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires random_access_range<Rng> && | |||
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return detail::is_heap_until_n( | |||
begin(rng), distance(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(is_heap_until) | |||
namespace cpp20 | |||
{ | |||
using ranges::is_heap_until; | |||
} | |||
RANGES_BEGIN_NIEBLOID(is_heap) | |||
/// \brief function template \c is_heap | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(is_heap)(I first, S last, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires random_access_iterator<I> && sentinel_for<S, I> && | |||
indirect_strict_weak_order<C, projected<I, P>>) | |||
{ | |||
return detail::is_heap_n(std::move(first), | |||
distance(first, last), | |||
std::move(pred), | |||
std::move(proj)); | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(is_heap)(Rng && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires random_access_range<Rng> && | |||
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return detail::is_heap_n( | |||
begin(rng), distance(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(is_heap) | |||
namespace cpp20 | |||
{ | |||
using ranges::is_heap; | |||
} | |||
/// @} | |||
/// \cond | |||
namespace detail | |||
{ | |||
struct sift_up_n_fn | |||
{ | |||
template<typename I, typename C = less, typename P = identity> | |||
void operator()(I first, iter_difference_t<I> len, C pred = C{}, | |||
P proj = P{}) const | |||
{ | |||
if(len > 1) | |||
{ | |||
I last = first + len; | |||
len = (len - 2) / 2; | |||
I i = first + len; | |||
if(invoke(pred, invoke(proj, *i), invoke(proj, *--last))) | |||
{ | |||
iter_value_t<I> v = iter_move(last); | |||
do | |||
{ | |||
*last = iter_move(i); | |||
last = i; | |||
if(len == 0) | |||
break; | |||
len = (len - 1) / 2; | |||
i = first + len; | |||
} while(invoke(pred, invoke(proj, *i), invoke(proj, v))); | |||
*last = std::move(v); | |||
} | |||
} | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(sift_up_n_fn, sift_up_n) | |||
struct sift_down_n_fn | |||
{ | |||
template<typename I, typename C = less, typename P = identity> | |||
void operator()(I first, iter_difference_t<I> len, I start, C pred = C{}, | |||
P proj = P{}) const | |||
{ | |||
// left-child of start is at 2 * start + 1 | |||
// right-child of start is at 2 * start + 2 | |||
auto child = start - first; | |||
if(len < 2 || (len - 2) / 2 < child) | |||
return; | |||
child = 2 * child + 1; | |||
I child_i = first + child; | |||
if((child + 1) < len && | |||
invoke(pred, invoke(proj, *child_i), invoke(proj, *(child_i + 1)))) | |||
{ | |||
// right-child exists and is greater than left-child | |||
++child_i; | |||
++child; | |||
} | |||
// check if we are in heap-order | |||
if(invoke(pred, invoke(proj, *child_i), invoke(proj, *start))) | |||
// we are, start is larger than it's largest child | |||
return; | |||
iter_value_t<I> top = iter_move(start); | |||
do | |||
{ | |||
// we are not in heap-order, swap the parent with it's largest child | |||
*start = iter_move(child_i); | |||
start = child_i; | |||
if((len - 2) / 2 < child) | |||
break; | |||
// recompute the child based off of the updated parent | |||
child = 2 * child + 1; | |||
child_i = first + child; | |||
if((child + 1) < len && | |||
invoke(pred, invoke(proj, *child_i), invoke(proj, *(child_i + 1)))) | |||
{ | |||
// right-child exists and is greater than left-child | |||
++child_i; | |||
++child; | |||
} | |||
// check if we are in heap-order | |||
} while(!invoke(pred, invoke(proj, *child_i), invoke(proj, top))); | |||
*start = std::move(top); | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(sift_down_n_fn, sift_down_n) | |||
} // namespace detail | |||
/// \endcond | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(push_heap) | |||
/// \brief function template \c push_heap | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(push_heap)( | |||
I first, S last, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires random_access_iterator<I> && sentinel_for<S, I> && | |||
sortable<I, C, P>) | |||
{ | |||
auto n = distance(first, last); | |||
detail::sift_up_n(first, n, std::move(pred), std::move(proj)); | |||
return first + n; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(push_heap)(Rng && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires random_access_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||
{ | |||
iterator_t<Rng> first = ranges::begin(rng); | |||
auto n = distance(rng); | |||
detail::sift_up_n(first, n, std::move(pred), std::move(proj)); | |||
return first + n; | |||
} | |||
RANGES_END_NIEBLOID(push_heap) | |||
namespace cpp20 | |||
{ | |||
using ranges::push_heap; | |||
} | |||
/// @} | |||
/// \cond | |||
namespace detail | |||
{ | |||
struct pop_heap_n_fn | |||
{ | |||
template<typename I, typename C = less, typename P = identity> | |||
auto operator()(I first, iter_difference_t<I> len, C pred = C{}, | |||
P proj = P{}) const -> CPP_ret(void)( // | |||
requires random_access_iterator<I> && sortable<I, C, P>) | |||
{ | |||
if(len > 1) | |||
{ | |||
ranges::iter_swap(first, first + (len - 1)); | |||
detail::sift_down_n( | |||
first, len - 1, first, std::move(pred), std::move(proj)); | |||
} | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(pop_heap_n_fn, pop_heap_n) | |||
} // namespace detail | |||
/// \endcond | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(pop_heap) | |||
/// \brief function template \c pop_heap | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(pop_heap)(I first, S last, C pred = C{}, P proj = P{}) | |||
->CPP_ret(I)( // | |||
requires random_access_iterator<I> && sentinel_for<S, I> && | |||
sortable<I, C, P>) | |||
{ | |||
auto n = distance(first, last); | |||
detail::pop_heap_n(first, n, std::move(pred), std::move(proj)); | |||
return first + n; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(pop_heap)(Rng && rng, C pred = C{}, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires random_access_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||
{ | |||
iterator_t<Rng> first = ranges::begin(rng); | |||
auto n = distance(rng); | |||
detail::pop_heap_n(first, n, std::move(pred), std::move(proj)); | |||
return first + n; | |||
} | |||
RANGES_END_NIEBLOID(pop_heap) | |||
namespace cpp20 | |||
{ | |||
using ranges::pop_heap; | |||
} | |||
RANGES_BEGIN_NIEBLOID(make_heap) | |||
/// \brief function template \c make_heap | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(make_heap)(I first, S last, C pred = C{}, P proj = P{}) | |||
->CPP_ret(I)( // | |||
requires random_access_iterator<I> && sentinel_for<S, I> && | |||
sortable<I, C, P>) | |||
{ | |||
iter_difference_t<I> const n = distance(first, last); | |||
if(n > 1) | |||
// start from the first parent, there is no need to consider children | |||
for(auto start = (n - 2) / 2; start >= 0; --start) | |||
detail::sift_down_n( | |||
first, n, first + start, std::ref(pred), std::ref(proj)); | |||
return first + n; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(make_heap)(Rng && rng, C pred = C{}, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires random_access_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||
{ | |||
iterator_t<Rng> first = ranges::begin(rng); | |||
auto const n = distance(rng); | |||
if(n > 1) | |||
// start from the first parent, there is no need to consider children | |||
for(auto start = (n - 2) / 2; start >= 0; --start) | |||
detail::sift_down_n( | |||
first, n, first + start, std::ref(pred), std::ref(proj)); | |||
return first + n; | |||
} | |||
RANGES_END_NIEBLOID(make_heap) | |||
namespace cpp20 | |||
{ | |||
using ranges::make_heap; | |||
} | |||
RANGES_BEGIN_NIEBLOID(sort_heap) | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(sort_heap)(I first, S last, C pred = C{}, P proj = P{}) | |||
->CPP_ret(I)( // | |||
requires random_access_iterator<I> && sentinel_for<S, I> && | |||
sortable<I, C, P>) | |||
{ | |||
iter_difference_t<I> const n = distance(first, last); | |||
for(auto i = n; i > 1; --i) | |||
detail::pop_heap_n(first, i, std::ref(pred), std::ref(proj)); | |||
return first + n; | |||
} | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(sort_heap)(Rng && rng, C pred = C{}, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires random_access_range<Rng &> && sortable<iterator_t<Rng>, C, P>) | |||
{ | |||
iterator_t<Rng> first = ranges::begin(rng); | |||
auto const n = distance(rng); | |||
for(auto i = n; i > 1; --i) | |||
detail::pop_heap_n(first, i, std::ref(pred), std::ref(proj)); | |||
return first + n; | |||
} | |||
RANGES_END_NIEBLOID(sort_heap) | |||
namespace cpp20 | |||
{ | |||
using ranges::sort_heap; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,303 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
//===----------------------------------------------------------------------===// | |||
// | |||
// The LLVM Compiler Infrastructure | |||
// | |||
// This file is dual licensed under the MIT and the University of Illinois Open | |||
// Source Licenses. See LICENSE.TXT for details. | |||
// | |||
//===----------------------------------------------------------------------===// | |||
#ifndef RANGES_V3_ALGORITHM_INPLACE_MERGE_HPP | |||
#define RANGES_V3_ALGORITHM_INPLACE_MERGE_HPP | |||
#include <functional> | |||
#include <memory> | |||
#include <new> | |||
#include <type_traits> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/lower_bound.hpp> | |||
#include <range/v3/algorithm/merge.hpp> | |||
#include <range/v3/algorithm/min.hpp> | |||
#include <range/v3/algorithm/move.hpp> | |||
#include <range/v3/algorithm/rotate.hpp> | |||
#include <range/v3/algorithm/upper_bound.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/functional/not_fn.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/move_iterators.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/reverse_iterator.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/memory.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
#include <range/v3/utility/swap.hpp> | |||
namespace ranges | |||
{ | |||
/// \cond | |||
namespace detail | |||
{ | |||
struct merge_adaptive_fn | |||
{ | |||
private: | |||
template<typename I, typename C, typename P> | |||
static void impl(I first, I middle, I last, iter_difference_t<I> len1, | |||
iter_difference_t<I> len2, iter_value_t<I> * const buf, | |||
C & pred, P & proj) | |||
{ | |||
auto tmpbuf = make_raw_buffer(buf); | |||
if(len1 <= len2) | |||
{ | |||
auto p = ranges::move(first, middle, tmpbuf.begin()).out; | |||
merge(make_move_iterator(buf), | |||
make_move_iterator(p.base().base()), | |||
make_move_iterator(std::move(middle)), | |||
make_move_iterator(std::move(last)), | |||
std::move(first), | |||
std::ref(pred), | |||
std::ref(proj), | |||
std::ref(proj)); | |||
} | |||
else | |||
{ | |||
auto p = ranges::move(middle, last, tmpbuf.begin()).out; | |||
using RBi = ranges::reverse_iterator<I>; | |||
using Rv = ranges::reverse_iterator<iter_value_t<I> *>; | |||
merge(make_move_iterator(RBi{std::move(middle)}), | |||
make_move_iterator(RBi{std::move(first)}), | |||
make_move_iterator(Rv{p.base().base()}), | |||
make_move_iterator(Rv{buf}), | |||
RBi{std::move(last)}, | |||
not_fn(std::ref(pred)), | |||
std::ref(proj), | |||
std::ref(proj)); | |||
} | |||
} | |||
public: | |||
template<typename I, typename C = less, typename P = identity> | |||
auto operator()(I first, I middle, I last, iter_difference_t<I> len1, | |||
iter_difference_t<I> len2, iter_value_t<I> * buf, | |||
std::ptrdiff_t buf_size, C pred = C{}, P proj = P{}) const | |||
-> CPP_ret(void)( // | |||
requires bidirectional_iterator<I> && sortable<I, C, P>) | |||
{ | |||
using D = iter_difference_t<I>; | |||
while(true) | |||
{ | |||
// if middle == last, we're done | |||
if(len2 == 0) | |||
return; | |||
// shrink [first, middle) as much as possible (with no moves), | |||
// returning if it shrinks to 0 | |||
for(; true; ++first, --len1) | |||
{ | |||
if(len1 == 0) | |||
return; | |||
if(invoke(pred, invoke(proj, *middle), invoke(proj, *first))) | |||
break; | |||
} | |||
if(len1 <= buf_size || len2 <= buf_size) | |||
{ | |||
merge_adaptive_fn::impl(std::move(first), | |||
std::move(middle), | |||
std::move(last), | |||
len1, | |||
len2, | |||
buf, | |||
pred, | |||
proj); | |||
return; | |||
} | |||
// first < middle < end | |||
// *first > *middle | |||
// partition [first, m1) [m1, middle) [middle, m2) [m2, last) such | |||
// that | |||
// all elements in: | |||
// [first, m1) <= [middle, m2) | |||
// [middle, m2) < [m1, middle) | |||
// [m1, middle) <= [m2, last) | |||
// and m1 or m2 is in the middle of its range | |||
I m1; // "median" of [first, middle) | |||
I m2; // "median" of [middle, last) | |||
D len11; // distance(first, m1) | |||
D len21; // distance(middle, m2) | |||
// binary search smaller range | |||
if(len1 < len2) | |||
{ // len >= 1, len2 >= 2 | |||
len21 = len2 / 2; | |||
m2 = next(middle, len21); | |||
m1 = upper_bound(first, | |||
middle, | |||
invoke(proj, *m2), | |||
std::ref(pred), | |||
std::ref(proj)); | |||
len11 = distance(first, m1); | |||
} | |||
else | |||
{ | |||
if(len1 == 1) | |||
{ // len1 >= len2 && len2 > 0, therefore len2 == 1 | |||
// It is known *first > *middle | |||
ranges::iter_swap(first, middle); | |||
return; | |||
} | |||
// len1 >= 2, len2 >= 1 | |||
len11 = len1 / 2; | |||
m1 = next(first, len11); | |||
m2 = lower_bound(middle, | |||
last, | |||
invoke(proj, *m1), | |||
std::ref(pred), | |||
std::ref(proj)); | |||
len21 = distance(middle, m2); | |||
} | |||
D len12 = len1 - len11; // distance(m1, middle) | |||
D len22 = len2 - len21; // distance(m2, last) | |||
// [first, m1) [m1, middle) [middle, m2) [m2, last) | |||
// swap middle two partitions | |||
middle = rotate(m1, std::move(middle), m2).begin(); | |||
// len12 and len21 now have swapped meanings | |||
// merge smaller range with recursive call and larger with tail | |||
// recursion elimination | |||
if(len11 + len21 < len12 + len22) | |||
{ | |||
(*this)(std::move(first), | |||
std::move(m1), | |||
middle, | |||
len11, | |||
len21, | |||
buf, | |||
buf_size, | |||
std::ref(pred), | |||
std::ref(proj)); | |||
first = std::move(middle); | |||
middle = std::move(m2); | |||
len1 = len12; | |||
len2 = len22; | |||
} | |||
else | |||
{ | |||
(*this)(middle, | |||
std::move(m2), | |||
std::move(last), | |||
len12, | |||
len22, | |||
buf, | |||
buf_size, | |||
std::ref(pred), | |||
std::ref(proj)); | |||
last = std::move(middle); | |||
middle = std::move(m1); | |||
len1 = len11; | |||
len2 = len21; | |||
} | |||
} | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(merge_adaptive_fn, merge_adaptive) | |||
struct inplace_merge_no_buffer_fn | |||
{ | |||
template<typename I, typename C = less, typename P = identity> | |||
auto operator()(I first, I middle, I last, iter_difference_t<I> len1, | |||
iter_difference_t<I> len2, C pred = C{}, P proj = P{}) const | |||
-> CPP_ret(void)( // | |||
requires bidirectional_iterator<I> && sortable<I, C, P>) | |||
{ | |||
merge_adaptive(std::move(first), | |||
std::move(middle), | |||
std::move(last), | |||
len1, | |||
len2, | |||
static_cast<iter_value_t<I> *>(nullptr), | |||
0, | |||
std::move(pred), | |||
std::move(proj)); | |||
} | |||
}; | |||
RANGES_INLINE_VARIABLE(inplace_merge_no_buffer_fn, inplace_merge_no_buffer) | |||
} // namespace detail | |||
/// \endcond | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(inplace_merge) | |||
// TODO reimplement to only need forward iterators | |||
/// \brief function template \c inplace_merge | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(inplace_merge)( | |||
I first, I middle, S last, C pred = C{}, P proj = P{}) | |||
->CPP_ret(I)( // | |||
requires bidirectional_iterator<I> && sortable<I, C, P>) | |||
{ | |||
using value_type = iter_value_t<I>; | |||
auto len1 = distance(first, middle); | |||
auto len2_and_end = enumerate(middle, last); | |||
auto buf_size = ranges::min(len1, len2_and_end.first); | |||
std::pair<value_type *, std::ptrdiff_t> buf{nullptr, 0}; | |||
std::unique_ptr<value_type, detail::return_temporary_buffer> h; | |||
if(detail::is_trivially_copy_assignable<value_type>::value && 8 < buf_size) | |||
{ | |||
buf = detail::get_temporary_buffer<value_type>(buf_size); | |||
h.reset(buf.first); | |||
} | |||
detail::merge_adaptive(std::move(first), | |||
std::move(middle), | |||
len2_and_end.second, | |||
len1, | |||
len2_and_end.first, | |||
buf.first, | |||
buf.second, | |||
std::move(pred), | |||
std::move(proj)); | |||
return len2_and_end.second; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(inplace_merge)( | |||
Rng && rng, iterator_t<Rng> middle, C pred = C{}, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires bidirectional_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||
{ | |||
return (*this)(begin(rng), | |||
std::move(middle), | |||
end(rng), | |||
std::move(pred), | |||
std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(inplace_merge) | |||
namespace cpp20 | |||
{ | |||
using ranges::inplace_merge; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,78 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
//===-------------------------- algorithm ---------------------------------===// | |||
// | |||
// The LLVM Compiler Infrastructure | |||
// | |||
// This file is dual licensed under the MIT and the University of Illinois Open | |||
// Source Licenses. See LICENSE.TXT for details. | |||
// | |||
//===----------------------------------------------------------------------===// | |||
#ifndef RANGES_V3_ALGORITHM_IS_PARTITIONED_HPP | |||
#define RANGES_V3_ALGORITHM_IS_PARTITIONED_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(is_partitioned) | |||
/// \brief function template \c is_partitioned | |||
template<typename I, typename S, typename C, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(is_partitioned)(I first, S last, C pred, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
indirect_unary_predicate<C, projected<I, P>>) | |||
{ | |||
for(; first != last; ++first) | |||
if(!invoke(pred, invoke(proj, *first))) | |||
break; | |||
for(; first != last; ++first) | |||
if(invoke(pred, invoke(proj, *first))) | |||
return false; | |||
return true; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(is_partitioned)(Rng && rng, C pred, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires input_range<Rng> && | |||
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(is_partitioned) | |||
namespace cpp20 | |||
{ | |||
using ranges::is_partitioned; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,75 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// Copyright Gonzalo Brito Gadeschi 2014 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
// Implementation based on the code in libc++ | |||
// http://http://libcxx.llvm.org/ | |||
#ifndef RANGES_V3_ALGORITHM_IS_SORTED_HPP | |||
#define RANGES_V3_ALGORITHM_IS_SORTED_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/is_sorted_until.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(is_sorted) | |||
/// \brief template function \c is_sorted | |||
/// | |||
/// range-based version of the \c is_sorted std algorithm | |||
/// | |||
/// Works on forward_ranges | |||
/// | |||
/// \pre `Rng` is a model of the `forward_range` concept | |||
/// \pre `I` is a model of the `forward_iterator` concept | |||
/// \pre `S` and `I` model the `sentinel_for<S, I>` concept | |||
/// \pre `R` and `projected<I, P>` model the `indirect_strict_weak_order<R, | |||
/// projected<I, P>>` concept | |||
/// | |||
template<typename I, typename S, typename R = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(is_sorted)(I first, S last, R rel = R{}, P proj = P{}) | |||
->CPP_ret(bool)( // | |||
requires forward_iterator<I> && sentinel_for<S, I> && | |||
indirect_strict_weak_order<R, projected<I, P>>) | |||
{ | |||
return is_sorted_until( | |||
std::move(first), last, std::move(rel), std::move(proj)) == last; | |||
} | |||
/// \overload | |||
template<typename Rng, typename R = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(is_sorted)(Rng && rng, R rel = R{}, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires forward_range<Rng> && | |||
indirect_strict_weak_order<R, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(rel), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(is_sorted) | |||
namespace cpp20 | |||
{ | |||
using ranges::is_sorted; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,87 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// Copyright Gonzalo Brito Gadeschi 2014 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
// Implementation based on the code in libc++ | |||
// http://http://libcxx.llvm.org/ | |||
#ifndef RANGES_V3_ALGORITHM_IS_SORTED_UNTIL_HPP | |||
#define RANGES_V3_ALGORITHM_IS_SORTED_UNTIL_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(is_sorted_until) | |||
/// \brief template function \c is_sorted_until | |||
/// | |||
/// range-based version of the \c is_sorted_until std algorithm | |||
/// | |||
/// Works on forward_ranges | |||
/// | |||
/// \pre `Rng` is a model of the `forward_range` concept | |||
/// \pre `I` is a model of the `forward_iterator` concept | |||
/// \pre `S` and `I` model the `sentinel_for<S, I>` concept | |||
/// \pre `R` and `projected<I, P>` model the `indirect_strict_weak_order<R, | |||
/// projected<I, P>>` concept | |||
/// | |||
template<typename I, typename S, typename R = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(is_sorted_until)( | |||
I first, S last, R pred = R{}, P proj = P{}) | |||
->CPP_ret(I)( // | |||
requires forward_iterator<I> && sentinel_for<S, I> && | |||
indirect_strict_weak_order<R, projected<I, P>>) | |||
{ | |||
auto i = first; | |||
if(first != last) | |||
{ | |||
while(++i != last) | |||
{ | |||
if(invoke(pred, invoke(proj, *i), invoke(proj, *first))) | |||
return i; | |||
first = i; | |||
} | |||
} | |||
return i; | |||
} | |||
/// \overload | |||
template<typename Rng, typename R = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(is_sorted_until)(Rng && rng, R pred = R{}, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires forward_range<Rng> && | |||
indirect_strict_weak_order<R, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(is_sorted_until) | |||
namespace cpp20 | |||
{ | |||
using ranges::is_sorted_until; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,97 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP | |||
#define RANGES_V3_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(lexicographical_compare) | |||
/// \brief function template \c lexicographical_compare | |||
template<typename I0, | |||
typename S0, | |||
typename I1, | |||
typename S1, | |||
typename C = less, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
auto RANGES_FUN_NIEBLOID(lexicographical_compare)(I0 begin0, | |||
S0 end0, | |||
I1 begin1, | |||
S1 end1, | |||
C pred = C{}, | |||
P0 proj0 = P0{}, | |||
P1 proj1 = P1{}) | |||
->CPP_ret(bool)( // | |||
requires input_iterator<I0> && sentinel_for<S0, I0> && | |||
input_iterator<I1> && sentinel_for<S1, I1> && | |||
indirect_strict_weak_order<C, projected<I0, P0>, projected<I1, P1>>) | |||
{ | |||
for(; begin1 != end1; ++begin0, ++begin1) | |||
{ | |||
if(begin0 == end0 || | |||
invoke(pred, invoke(proj0, *begin0), invoke(proj1, *begin1))) | |||
return true; | |||
if(invoke(pred, invoke(proj1, *begin1), invoke(proj0, *begin0))) | |||
return false; | |||
} | |||
return false; | |||
} | |||
/// \overload | |||
template<typename Rng0, | |||
typename Rng1, | |||
typename C = less, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
auto RANGES_FUN_NIEBLOID(lexicographical_compare)( | |||
Rng0 && rng0, Rng1 && rng1, C pred = C{}, P0 proj0 = P0{}, P1 proj1 = P1{}) // | |||
->CPP_ret(bool)( // | |||
requires input_range<Rng0> && input_range<Rng1> && | |||
indirect_strict_weak_order<C, | |||
projected<iterator_t<Rng0>, P0>, | |||
projected<iterator_t<Rng1>, P1>>) | |||
{ | |||
return (*this)(begin(rng0), | |||
end(rng0), | |||
begin(rng1), | |||
end(rng1), | |||
std::move(pred), | |||
std::move(proj0), | |||
std::move(proj1)); | |||
} | |||
RANGES_END_NIEBLOID(lexicographical_compare) | |||
namespace cpp20 | |||
{ | |||
using ranges::lexicographical_compare; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,76 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// Copyright Casey Carter 2016 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_LOWER_BOUND_HPP | |||
#define RANGES_V3_ALGORITHM_LOWER_BOUND_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/aux_/lower_bound_n.hpp> | |||
#include <range/v3/algorithm/partition_point.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(lower_bound) | |||
/// \brief function template \c lower_bound | |||
template<typename I, | |||
typename S, | |||
typename V, | |||
typename C = less, | |||
typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(lower_bound)( | |||
I first, S last, V const & val, C pred = C{}, P proj = P{}) | |||
->CPP_ret(I)( // | |||
requires forward_iterator<I> && sentinel_for<S, I> && | |||
indirect_strict_weak_order<C, V const *, projected<I, P>>) | |||
{ | |||
return partition_point(std::move(first), | |||
std::move(last), | |||
detail::make_lower_bound_predicate(pred, val), | |||
std::move(proj)); | |||
} | |||
/// \overload | |||
template<typename Rng, typename V, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(lower_bound)( | |||
Rng && rng, V const & val, C pred = C{}, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires forward_range<Rng> && | |||
indirect_strict_weak_order<C, V const *, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return partition_point( | |||
rng, detail::make_lower_bound_predicate(pred, val), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(lower_bound) | |||
namespace cpp20 | |||
{ | |||
using ranges::lower_bound; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,88 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// Copyright Casey Carter 2015 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_MAX_HPP | |||
#define RANGES_V3_ALGORITHM_MAX_HPP | |||
#include <initializer_list> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(max) | |||
/// \brief function template \c max | |||
template<typename T, typename C = less, typename P = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(max)( | |||
T const & a, T const & b, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(T const &)( // | |||
requires indirect_strict_weak_order<C, projected<T const *, P>>) | |||
{ | |||
return invoke(pred, invoke(proj, b), invoke(proj, a)) ? a : b; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(max)(Rng && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(range_value_t<Rng>)( // | |||
requires input_range<Rng> && | |||
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>> && | |||
indirectly_copyable_storable<iterator_t<Rng>, range_value_t<Rng> *>) | |||
{ | |||
auto first = ranges::begin(rng); | |||
auto last = ranges::end(rng); | |||
RANGES_EXPECT(first != last); | |||
range_value_t<Rng> result = *first; | |||
while(++first != last) | |||
{ | |||
auto && tmp = *first; | |||
if(invoke(pred, invoke(proj, result), invoke(proj, tmp))) | |||
result = (decltype(tmp) &&)tmp; | |||
} | |||
return result; | |||
} | |||
/// \overload | |||
template<typename T, typename C = less, typename P = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(max)( | |||
std::initializer_list<T> const && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(T)( // | |||
requires copyable<T> && | |||
indirect_strict_weak_order<C, projected<T const *, P>>) | |||
{ | |||
return (*this)(rng, std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(max) | |||
namespace cpp20 | |||
{ | |||
using ranges::max; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,69 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_MAX_ELEMENT_HPP | |||
#define RANGES_V3_ALGORITHM_MAX_ELEMENT_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(max_element) | |||
/// \brief function template \c max_element | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(max_element)(I first, S last, C pred = C{}, P proj = P{}) | |||
->CPP_ret(I)( // | |||
requires forward_iterator<I> && sentinel_for<S, I> && | |||
indirect_strict_weak_order<C, projected<I, P>>) | |||
{ | |||
if(first != last) | |||
for(auto tmp = next(first); tmp != last; ++tmp) | |||
if(invoke(pred, invoke(proj, *first), invoke(proj, *tmp))) | |||
first = tmp; | |||
return first; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(max_element)(Rng && rng, C pred = C{}, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires forward_range<Rng> && | |||
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(max_element) | |||
namespace cpp20 | |||
{ | |||
using ranges::max_element; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,133 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
// Copyright (c) 2009 Alexander Stepanov and Paul McJones | |||
// | |||
// Permission to use, copy, modify, distribute and sell this software | |||
// and its documentation for any purpose is hereby granted without | |||
// fee, provided that the above copyright notice appear in all copies | |||
// and that both that copyright notice and this permission notice | |||
// appear in supporting documentation. The authors make no | |||
// representations about the suitability of this software for any | |||
// purpose. It is provided "as is" without express or implied | |||
// warranty. | |||
// | |||
// Algorithms from | |||
// Elements of Programming | |||
// by Alexander Stepanov and Paul McJones | |||
// Addison-Wesley Professional, 2009 | |||
#ifndef RANGES_V3_ALGORITHM_MERGE_HPP | |||
#define RANGES_V3_ALGORITHM_MERGE_HPP | |||
#include <tuple> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/copy.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I0, typename I1, typename O> | |||
using merge_result = detail::in1_in2_out_result<I0, I1, O>; | |||
RANGES_BEGIN_NIEBLOID(merge) | |||
/// \brief function template \c merge | |||
template<typename I0, | |||
typename S0, | |||
typename I1, | |||
typename S1, | |||
typename O, | |||
typename C = less, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
auto RANGES_FUN_NIEBLOID(merge)(I0 begin0, | |||
S0 end0, | |||
I1 begin1, | |||
S1 end1, | |||
O out, | |||
C pred = C{}, | |||
P0 proj0 = P0{}, | |||
P1 proj1 = P1{}) // | |||
->CPP_ret(merge_result<I0, I1, O>)( // | |||
requires sentinel_for<S0, I0> && sentinel_for<S1, I1> && | |||
mergeable<I0, I1, O, C, P0, P1>) | |||
{ | |||
for(; begin0 != end0 && begin1 != end1; ++out) | |||
{ | |||
if(invoke(pred, invoke(proj1, *begin1), invoke(proj0, *begin0))) | |||
{ | |||
*out = *begin1; | |||
++begin1; | |||
} | |||
else | |||
{ | |||
*out = *begin0; | |||
++begin0; | |||
} | |||
} | |||
auto t0 = ranges::copy(begin0, end0, out); | |||
auto t1 = ranges::copy(begin1, end1, t0.out); | |||
return {t0.in, t1.in, t1.out}; | |||
} | |||
/// \overload | |||
template<typename Rng0, | |||
typename Rng1, | |||
typename O, | |||
typename C = less, | |||
typename P0 = identity, | |||
typename P1 = identity> | |||
auto RANGES_FUN_NIEBLOID(merge)(Rng0 && rng0, | |||
Rng1 && rng1, | |||
O out, | |||
C pred = C{}, | |||
P0 proj0 = P0{}, | |||
P1 proj1 = P1{}) | |||
->CPP_ret(merge_result<safe_iterator_t<Rng0>, safe_iterator_t<Rng1>, O>)( // | |||
requires range<Rng0> && range<Rng1> && | |||
mergeable<iterator_t<Rng0>, iterator_t<Rng1>, O, C, P0, P1>) | |||
{ | |||
return (*this)(begin(rng0), | |||
end(rng0), | |||
begin(rng1), | |||
end(rng1), | |||
std::move(out), | |||
std::move(pred), | |||
std::move(proj0), | |||
std::move(proj1)); | |||
} | |||
RANGES_END_NIEBLOID(merge) | |||
namespace cpp20 | |||
{ | |||
using ranges::merge; | |||
using ranges::merge_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,88 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// Copyright Casey Carter 2015 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_MIN_HPP | |||
#define RANGES_V3_ALGORITHM_MIN_HPP | |||
#include <initializer_list> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(min) | |||
/// \brief function template \c min | |||
template<typename T, typename C = less, typename P = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(min)( | |||
T const & a, T const & b, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(T const &)( // | |||
requires indirect_strict_weak_order<C, projected<T const *, P>>) | |||
{ | |||
return invoke(pred, invoke(proj, b), invoke(proj, a)) ? b : a; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(min)(Rng && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(range_value_t<Rng>)( // | |||
requires input_range<Rng> && | |||
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>> && | |||
indirectly_copyable_storable<iterator_t<Rng>, range_value_t<Rng> *>) | |||
{ | |||
auto first = ranges::begin(rng); | |||
auto last = ranges::end(rng); | |||
RANGES_EXPECT(first != last); | |||
range_value_t<Rng> result = *first; | |||
while(++first != last) | |||
{ | |||
auto && tmp = *first; | |||
if(invoke(pred, invoke(proj, tmp), invoke(proj, result))) | |||
result = (decltype(tmp) &&)tmp; | |||
} | |||
return result; | |||
} | |||
/// \overload | |||
template<typename T, typename C = less, typename P = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(min)( | |||
std::initializer_list<T> const && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(T)( // | |||
requires copyable<T> && | |||
indirect_strict_weak_order<C, projected<T const *, P>>) | |||
{ | |||
return (*this)(rng, std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(min) | |||
namespace cpp20 | |||
{ | |||
using ranges::min; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,70 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_MIN_ELEMENT_HPP | |||
#define RANGES_V3_ALGORITHM_MIN_ELEMENT_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(min_element) | |||
/// \brief function template \c min_element | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(min_element)( | |||
I first, S last, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires forward_iterator<I> && sentinel_for<S, I> && | |||
indirect_strict_weak_order<C, projected<I, P>>) | |||
{ | |||
if(first != last) | |||
for(auto tmp = next(first); tmp != last; ++tmp) | |||
if(invoke(pred, invoke(proj, *tmp), invoke(proj, *first))) | |||
first = tmp; | |||
return first; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(min_element)(Rng && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires forward_range<Rng> && | |||
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(min_element) | |||
namespace cpp20 | |||
{ | |||
using ranges::min_element; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,129 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// Copyright Casey Carter 2015 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_MINMAX_HPP | |||
#define RANGES_V3_ALGORITHM_MINMAX_HPP | |||
#include <initializer_list> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename T> | |||
using minmax_result = detail::min_max_result<T, T>; | |||
RANGES_BEGIN_NIEBLOID(minmax) | |||
/// \brief function template \c minmax | |||
template<typename T, typename C = less, typename P = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(minmax)( | |||
T const & a, T const & b, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(minmax_result<T const &>)( // | |||
requires indirect_strict_weak_order<C, projected<T const *, P>>) | |||
{ | |||
using R = minmax_result<T const &>; | |||
return invoke(pred, invoke(proj, b), invoke(proj, a)) ? R{b, a} : R{a, b}; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(minmax)( | |||
Rng && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(minmax_result<range_value_t<Rng>>)( // | |||
requires input_range<Rng> && | |||
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>> && | |||
indirectly_copyable_storable<iterator_t<Rng>, range_value_t<Rng> *>) | |||
{ | |||
using R = minmax_result<range_value_t<Rng>>; | |||
auto first = ranges::begin(rng); | |||
auto last = ranges::end(rng); | |||
RANGES_EXPECT(first != last); | |||
auto result = R{*first, *first}; | |||
if(++first != last) | |||
{ | |||
{ | |||
auto && tmp = *first; | |||
if(invoke(pred, invoke(proj, tmp), invoke(proj, result.min))) | |||
result.min = (decltype(tmp) &&)tmp; | |||
else | |||
result.max = (decltype(tmp) &&)tmp; | |||
} | |||
while(++first != last) | |||
{ | |||
range_value_t<Rng> tmp1 = *first; | |||
if(++first == last) | |||
{ | |||
if(invoke(pred, invoke(proj, tmp1), invoke(proj, result.min))) | |||
result.min = std::move(tmp1); | |||
else if(!invoke( | |||
pred, invoke(proj, tmp1), invoke(proj, result.max))) | |||
result.max = std::move(tmp1); | |||
break; | |||
} | |||
auto && tmp2 = *first; | |||
if(invoke(pred, invoke(proj, tmp2), invoke(proj, tmp1))) | |||
{ | |||
if(invoke(pred, invoke(proj, tmp2), invoke(proj, result.min))) | |||
result.min = (decltype(tmp2) &&)tmp2; | |||
if(!invoke(pred, invoke(proj, tmp1), invoke(proj, result.max))) | |||
result.max = std::move(tmp1); | |||
} | |||
else | |||
{ | |||
if(invoke(pred, invoke(proj, tmp1), invoke(proj, result.min))) | |||
result.min = std::move(tmp1); | |||
if(!invoke(pred, invoke(proj, tmp2), invoke(proj, result.max))) | |||
result.max = (decltype(tmp2) &&)tmp2; | |||
} | |||
} | |||
} | |||
return result; | |||
} | |||
/// \overload | |||
template<typename T, typename C = less, typename P = identity> | |||
constexpr auto RANGES_FUN_NIEBLOID(minmax)( | |||
std::initializer_list<T> const && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(minmax_result<T>)( // | |||
requires copyable<T> && | |||
indirect_strict_weak_order<C, projected<T const *, P>>) | |||
{ | |||
return (*this)(rng, std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(minmax) | |||
namespace cpp20 | |||
{ | |||
using ranges::minmax; | |||
using ranges::minmax_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,110 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
// Implementation based on the code in libc++ | |||
// http://http://libcxx.llvm.org/ | |||
#ifndef RANGES_V3_ALGORITHM_MINMAX_ELEMENT_HPP | |||
#define RANGES_V3_ALGORITHM_MINMAX_ELEMENT_HPP | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I> | |||
using minmax_element_result = detail::min_max_result<I, I>; | |||
RANGES_BEGIN_NIEBLOID(minmax_element) | |||
/// \brief function template \c minmax_element | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(minmax_element)( | |||
I first, S last, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(minmax_element_result<I>)( // | |||
requires forward_iterator<I> && sentinel_for<S, I> && | |||
indirect_strict_weak_order<C, projected<I, P>>) | |||
{ | |||
minmax_element_result<I> result{first, first}; | |||
if(first == last || ++first == last) | |||
return result; | |||
if(invoke(pred, invoke(proj, *first), invoke(proj, *result.min))) | |||
result.min = first; | |||
else | |||
result.max = first; | |||
while(++first != last) | |||
{ | |||
I tmp = first; | |||
if(++first == last) | |||
{ | |||
if(invoke(pred, invoke(proj, *tmp), invoke(proj, *result.min))) | |||
result.min = tmp; | |||
else if(!invoke(pred, invoke(proj, *tmp), invoke(proj, *result.max))) | |||
result.max = tmp; | |||
break; | |||
} | |||
else | |||
{ | |||
if(invoke(pred, invoke(proj, *first), invoke(proj, *tmp))) | |||
{ | |||
if(invoke(pred, invoke(proj, *first), invoke(proj, *result.min))) | |||
result.min = first; | |||
if(!invoke(pred, invoke(proj, *tmp), invoke(proj, *result.max))) | |||
result.max = tmp; | |||
} | |||
else | |||
{ | |||
if(invoke(pred, invoke(proj, *tmp), invoke(proj, *result.min))) | |||
result.min = tmp; | |||
if(!invoke(pred, invoke(proj, *first), invoke(proj, *result.max))) | |||
result.max = first; | |||
} | |||
} | |||
} | |||
return result; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(minmax_element)( | |||
Rng && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(minmax_element_result<safe_iterator_t<Rng>>)( // | |||
requires forward_range<Rng> && | |||
indirect_strict_weak_order<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(minmax_element) | |||
namespace cpp20 | |||
{ | |||
using ranges::minmax_element; | |||
using ranges::minmax_element_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,170 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_MISMATCH_HPP | |||
#define RANGES_V3_ALGORITHM_MISMATCH_HPP | |||
#include <utility> | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I1, typename I2> | |||
using mismatch_result = detail::in1_in2_result<I1, I2>; | |||
RANGES_BEGIN_NIEBLOID(mismatch) | |||
/// \brief function template \c mismatch | |||
template<typename I1, | |||
typename S1, | |||
typename I2, | |||
typename C = equal_to, | |||
typename P1 = identity, | |||
typename P2 = identity> | |||
RANGES_DEPRECATED( | |||
"Use the variant of ranges::mismatch that takes an upper bound for " | |||
"both sequences") | |||
auto RANGES_FUN_NIEBLOID(mismatch)(I1 begin1, | |||
S1 end1, | |||
I2 begin2, | |||
C pred = C{}, | |||
P1 proj1 = P1{}, | |||
P2 proj2 = P2{}) // | |||
->CPP_ret(mismatch_result<I1, I2>)( // | |||
requires input_iterator<I1> && sentinel_for<S1, I1> && | |||
input_iterator<I2> && | |||
indirect_relation<C, projected<I1, P1>, projected<I2, P2>>) | |||
{ | |||
for(; begin1 != end1; ++begin1, ++begin2) | |||
if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2))) | |||
break; | |||
return {begin1, begin2}; | |||
} | |||
/// \overload | |||
template<typename I1, | |||
typename S1, | |||
typename I2, | |||
typename S2, | |||
typename C = equal_to, | |||
typename P1 = identity, | |||
typename P2 = identity> | |||
auto RANGES_FUN_NIEBLOID(mismatch)(I1 begin1, | |||
S1 end1, | |||
I2 begin2, | |||
S2 end2, | |||
C pred = C{}, | |||
P1 proj1 = P1{}, | |||
P2 proj2 = P2{}) // | |||
->CPP_ret(mismatch_result<I1, I2>)( // | |||
requires input_iterator<I1> && sentinel_for<S1, I1> && | |||
input_iterator<I2> && sentinel_for<S2, I2> && | |||
indirect_relation<C, projected<I1, P1>, projected<I2, P2>>) | |||
{ | |||
for(; begin1 != end1 && begin2 != end2; ++begin1, ++begin2) | |||
if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2))) | |||
break; | |||
return {begin1, begin2}; | |||
} | |||
/// \overload | |||
template<typename Rng1, | |||
typename I2Ref, | |||
typename C = equal_to, | |||
typename P1 = identity, | |||
typename P2 = identity> | |||
RANGES_DEPRECATED( | |||
"Use the variant of ranges::mismatch that takes an upper bound for " | |||
"both sequences") | |||
auto RANGES_FUN_NIEBLOID(mismatch)(Rng1 && rng1, | |||
I2Ref && begin2, | |||
C pred = C{}, // see below [*] | |||
P1 proj1 = P1{}, | |||
P2 proj2 = P2{}) // | |||
->CPP_ret(mismatch_result<safe_iterator_t<Rng1>, uncvref_t<I2Ref>>)( // | |||
requires input_range<Rng1> && input_iterator<uncvref_t<I2Ref>> && | |||
indirect_relation<C, | |||
projected<iterator_t<Rng1>, P1>, | |||
projected<uncvref_t<I2Ref>, P2>>) | |||
{ | |||
RANGES_DIAGNOSTIC_PUSH | |||
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS | |||
return (*this)(begin(rng1), | |||
end(rng1), | |||
static_cast<uncvref_t<I2Ref> &&>(begin2), | |||
std::move(pred), | |||
std::move(proj1), | |||
std::move(proj2)); | |||
RANGES_DIAGNOSTIC_POP | |||
} | |||
/// \overload | |||
template<typename Rng1, | |||
typename Rng2, | |||
typename C = equal_to, | |||
typename P1 = identity, | |||
typename P2 = identity> | |||
auto RANGES_FUN_NIEBLOID(mismatch)( | |||
Rng1 && rng1, Rng2 && rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) // | |||
->CPP_ret(mismatch_result<safe_iterator_t<Rng1>, safe_iterator_t<Rng2>>)( // | |||
requires input_range<Rng1> && input_range<Rng2> && | |||
indirect_relation<C, | |||
projected<iterator_t<Rng1>, P1>, | |||
projected<iterator_t<Rng2>, P2>>) | |||
{ | |||
return (*this)(begin(rng1), | |||
end(rng1), | |||
begin(rng2), | |||
end(rng2), | |||
std::move(pred), | |||
std::move(proj1), | |||
std::move(proj2)); | |||
} | |||
RANGES_END_NIEBLOID(mismatch) | |||
namespace cpp20 | |||
{ | |||
using ranges::mismatch; | |||
using ranges::mismatch_result; | |||
} // namespace cpp20 | |||
// [*] In this case, the 'begin2' iterator is taken by universal reference. Why? So | |||
// that we can properly distinguish this case: | |||
// int x[] = {1,2,3,4}; | |||
// int y[] = {1,2,3,4}; | |||
// mismatch(x, y); | |||
// Had 'begin2' been taken by value as is customary, this call could match as either | |||
// two ranges, or a range and an iterator, where the iterator is the array, decayed | |||
// to a pointer. Yuk! | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,85 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_MOVE_HPP | |||
#define RANGES_V3_ALGORITHM_MOVE_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/move.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename O> | |||
using move_result = detail::in_out_result<I, O>; | |||
RANGES_HIDDEN_DETAIL(namespace _move CPP_PP_LBRACE()) | |||
RANGES_BEGIN_NIEBLOID(move) | |||
/// \brief function template \c move | |||
template<typename I, typename S, typename O> | |||
auto RANGES_FUN_NIEBLOID(move)(I first, S last, O out) // | |||
->CPP_ret(move_result<I, O>)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
weakly_incrementable<O> && indirectly_movable<I, O>) | |||
{ | |||
for(; first != last; ++first, ++out) | |||
*out = iter_move(first); | |||
return {first, out}; | |||
} | |||
/// \overload | |||
template<typename Rng, typename O> | |||
auto RANGES_FUN_NIEBLOID(move)(Rng && rng, O out) // | |||
->CPP_ret(move_result<safe_iterator_t<Rng>, O>)( // | |||
requires input_range<Rng> && weakly_incrementable<O> && | |||
indirectly_movable<iterator_t<Rng>, O>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(out)); | |||
} | |||
RANGES_END_NIEBLOID(move) | |||
RANGES_HIDDEN_DETAIL(CPP_PP_RBRACE()) | |||
#ifndef RANGES_DOXYGEN_INVOKED | |||
struct RANGES_EMPTY_BASES move_fn | |||
: aux::move_fn | |||
, _move::move_fn | |||
{ | |||
using aux::move_fn::operator(); | |||
using _move::move_fn::operator(); | |||
}; | |||
RANGES_INLINE_VARIABLE(move_fn, move) | |||
#endif | |||
namespace cpp20 | |||
{ | |||
using ranges::move_result; | |||
using ranges::RANGES_HIDDEN_DETAIL(_move::) move; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,72 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_MOVE_BACKWARD_HPP | |||
#define RANGES_V3_ALGORITHM_MOVE_BACKWARD_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename O> | |||
using move_backward_result = detail::in_out_result<I, O>; | |||
RANGES_BEGIN_NIEBLOID(move_backward) | |||
/// \brief function template \c move_backward | |||
template<typename I, typename S, typename O> | |||
auto RANGES_FUN_NIEBLOID(move_backward)(I first, S end_, O out) // | |||
->CPP_ret(move_backward_result<I, O>)( // | |||
requires bidirectional_iterator<I> && sentinel_for<S, I> && | |||
bidirectional_iterator<O> && indirectly_movable<I, O>) | |||
{ | |||
I i = ranges::next(first, end_), last = i; | |||
while(first != i) | |||
*--out = iter_move(--i); | |||
return {last, out}; | |||
} | |||
/// \overload | |||
template<typename Rng, typename O> | |||
auto RANGES_FUN_NIEBLOID(move_backward)(Rng && rng, O out) // | |||
->CPP_ret(move_backward_result<safe_iterator_t<Rng>, O>)( // | |||
requires bidirectional_range<Rng> && bidirectional_iterator<O> && | |||
indirectly_movable<iterator_t<Rng>, O>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(out)); | |||
} | |||
RANGES_END_NIEBLOID(move_backward) | |||
namespace cpp20 | |||
{ | |||
using ranges::move_backward; | |||
using ranges::move_backward_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,68 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Andrew Sutton 2014 | |||
// Copyright Gonzalo Brito Gadeschi 2014 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_NONE_OF_HPP | |||
#define RANGES_V3_ALGORITHM_NONE_OF_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(none_of) | |||
/// \brief function template \c none_of | |||
template<typename I, typename S, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(none_of)(I first, S last, F pred, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
indirect_unary_predicate<F, projected<I, P>>) | |||
{ | |||
for(; first != last; ++first) | |||
if(invoke(pred, invoke(proj, *first))) | |||
return false; | |||
return true; | |||
} | |||
/// \overload | |||
template<typename Rng, typename F, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(none_of)(Rng && rng, F pred, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires input_range<Rng> && | |||
indirect_unary_predicate<F, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(none_of) | |||
namespace cpp20 | |||
{ | |||
using ranges::none_of; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,329 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
//===----------------------------------------------------------------------===// | |||
// | |||
// The LLVM Compiler Infrastructure | |||
// | |||
// This file is dual licensed under the MIT and the University of Illinois Open | |||
// Source Licenses. See LICENSE.TXT for details. | |||
// | |||
//===----------------------------------------------------------------------===// | |||
#ifndef RANGES_V3_ALGORITHM_NTH_ELEMENT_HPP | |||
#define RANGES_V3_ALGORITHM_NTH_ELEMENT_HPP | |||
#include <utility> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/min_element.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
#include <range/v3/utility/swap.hpp> | |||
namespace ranges | |||
{ | |||
/// \cond | |||
namespace detail | |||
{ | |||
// stable, 2-3 compares, 0-2 swaps | |||
template<typename I, typename C, typename P> | |||
auto sort3(I x, I y, I z, C & pred, P & proj) -> CPP_ret(unsigned)( // | |||
requires forward_iterator<I> && indirect_relation<C, projected<I, P>>) | |||
{ | |||
unsigned r = 0; | |||
if(!invoke(pred, invoke(proj, *y), invoke(proj, *x))) // if x <= y | |||
{ | |||
if(!invoke(pred, invoke(proj, *z), invoke(proj, *y))) // if y <= z | |||
return r; // x <= y && y <= z | |||
// x <= y && y > z | |||
ranges::iter_swap(y, z); // x <= z && y < z | |||
r = 1; | |||
if(invoke(pred, invoke(proj, *y), invoke(proj, *x))) // if x > y | |||
{ | |||
ranges::iter_swap(x, y); // x < y && y <= z | |||
r = 2; | |||
} | |||
return r; // x <= y && y < z | |||
} | |||
if(invoke(pred, invoke(proj, *z), invoke(proj, *y))) // x > y, if y > z | |||
{ | |||
ranges::iter_swap(x, z); // x < y && y < z | |||
r = 1; | |||
return r; | |||
} | |||
ranges::iter_swap(x, y); // x > y && y <= z | |||
r = 1; // x < y && x <= z | |||
if(invoke(pred, invoke(proj, *z), invoke(proj, *y))) // if y > z | |||
{ | |||
ranges::iter_swap(y, z); // x <= y && y < z | |||
r = 2; | |||
} | |||
return r; | |||
} // x <= y && y <= z | |||
template<typename I, typename C, typename P> | |||
auto selection_sort(I first, I last, C & pred, P & proj) -> CPP_ret(void)( // | |||
requires bidirectional_iterator<I> && indirect_relation<C, projected<I, P>>) | |||
{ | |||
RANGES_EXPECT(first != last); | |||
for(I lm1 = ranges::prev(last); first != lm1; ++first) | |||
{ | |||
I i = ranges::min_element(first, last, std::ref(pred), std::ref(proj)); | |||
if(i != first) | |||
ranges::iter_swap(first, i); | |||
} | |||
} | |||
} // namespace detail | |||
/// \endcond | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(nth_element) | |||
/// \brief function template \c nth_element | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(nth_element)( | |||
I first, I nth, S end_, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires random_access_iterator<I> && sortable<I, C, P>) | |||
{ | |||
I last = ranges::next(nth, end_), end_orig = last; | |||
// C is known to be a reference type | |||
using difference_type = iter_difference_t<I>; | |||
difference_type const limit = 7; | |||
while(true) | |||
{ | |||
restart: | |||
if(nth == last) | |||
return end_orig; | |||
difference_type len = last - first; | |||
switch(len) | |||
{ | |||
case 0: | |||
case 1: | |||
return end_orig; | |||
case 2: | |||
if(invoke(pred, invoke(proj, *--last), invoke(proj, *first))) | |||
ranges::iter_swap(first, last); | |||
return end_orig; | |||
case 3: | |||
{ | |||
I m = first; | |||
detail::sort3(first, ++m, --last, pred, proj); | |||
return end_orig; | |||
} | |||
} | |||
if(len <= limit) | |||
{ | |||
detail::selection_sort(first, last, pred, proj); | |||
return end_orig; | |||
} | |||
// len > limit >= 3 | |||
I m = first + len / 2; | |||
I lm1 = last; | |||
unsigned n_swaps = detail::sort3(first, m, --lm1, pred, proj); | |||
// *m is median | |||
// partition [first, m) < *m and *m <= [m, last) | |||
//(this inhibits tossing elements equivalent to m around unnecessarily) | |||
I i = first; | |||
I j = lm1; | |||
// j points beyond range to be tested, *lm1 is known to be <= *m | |||
// The search going up is known to be guarded but the search coming down | |||
// isn't. Prime the downward search with a guard. | |||
if(!invoke(pred, invoke(proj, *i), invoke(proj, *m))) // if *first == *m | |||
{ | |||
// *first == *m, *first doesn't go in first part | |||
// manually guard downward moving j against i | |||
while(true) | |||
{ | |||
if(i == --j) | |||
{ | |||
// *first == *m, *m <= all other elements | |||
// Parition instead into [first, i) == *first and *first < [i, | |||
// last) | |||
++i; // first + 1 | |||
j = last; | |||
if(!invoke( | |||
pred, | |||
invoke(proj, *first), | |||
invoke( | |||
proj, | |||
*--j))) // we need a guard if *first == *(last-1) | |||
{ | |||
while(true) | |||
{ | |||
if(i == j) | |||
return end_orig; // [first, last) all equivalent | |||
// elements | |||
if(invoke( | |||
pred, invoke(proj, *first), invoke(proj, *i))) | |||
{ | |||
ranges::iter_swap(i, j); | |||
++n_swaps; | |||
++i; | |||
break; | |||
} | |||
++i; | |||
} | |||
} | |||
// [first, i) == *first and *first < [j, last) and j == last - | |||
// 1 | |||
if(i == j) | |||
return end_orig; | |||
while(true) | |||
{ | |||
while( | |||
!invoke(pred, invoke(proj, *first), invoke(proj, *i))) | |||
++i; | |||
while(invoke( | |||
pred, invoke(proj, *first), invoke(proj, *--j))) | |||
; | |||
if(i >= j) | |||
break; | |||
ranges::iter_swap(i, j); | |||
++n_swaps; | |||
++i; | |||
} | |||
// [first, i) == *first and *first < [i, last) | |||
// The first part is sorted, | |||
if(nth < i) | |||
return end_orig; | |||
// nth_element the second part | |||
// nth_element<C>(i, nth, last, pred); | |||
first = i; | |||
goto restart; | |||
} | |||
if(invoke(pred, invoke(proj, *j), invoke(proj, *m))) | |||
{ | |||
ranges::iter_swap(i, j); | |||
++n_swaps; | |||
break; // found guard for downward moving j, now use unguarded | |||
// partition | |||
} | |||
} | |||
} | |||
++i; | |||
// j points beyond range to be tested, *lm1 is known to be <= *m | |||
// if not yet partitioned... | |||
if(i < j) | |||
{ | |||
// known that *(i - 1) < *m | |||
while(true) | |||
{ | |||
// m still guards upward moving i | |||
while(invoke(pred, invoke(proj, *i), invoke(proj, *m))) | |||
++i; | |||
// It is now known that a guard exists for downward moving j | |||
while(!invoke(pred, invoke(proj, *--j), invoke(proj, *m))) | |||
; | |||
if(i >= j) | |||
break; | |||
ranges::iter_swap(i, j); | |||
++n_swaps; | |||
// It is known that m != j | |||
// If m just moved, follow it | |||
if(m == i) | |||
m = j; | |||
++i; | |||
} | |||
} | |||
// [first, i) < *m and *m <= [i, last) | |||
if(i != m && invoke(pred, invoke(proj, *m), invoke(proj, *i))) | |||
{ | |||
ranges::iter_swap(i, m); | |||
++n_swaps; | |||
} | |||
// [first, i) < *i and *i <= [i+1, last) | |||
if(nth == i) | |||
return end_orig; | |||
if(n_swaps == 0) | |||
{ | |||
// We were given a perfectly partitioned sequence. Coincidence? | |||
if(nth < i) | |||
{ | |||
// Check for [first, i) already sorted | |||
j = m = first; | |||
while(++j != i) | |||
{ | |||
if(invoke(pred, invoke(proj, *j), invoke(proj, *m))) | |||
// not yet sorted, so sort | |||
goto not_sorted; | |||
m = j; | |||
} | |||
// [first, i) sorted | |||
return end_orig; | |||
} | |||
else | |||
{ | |||
// Check for [i, last) already sorted | |||
j = m = i; | |||
while(++j != last) | |||
{ | |||
if(invoke(pred, invoke(proj, *j), invoke(proj, *m))) | |||
// not yet sorted, so sort | |||
goto not_sorted; | |||
m = j; | |||
} | |||
// [i, last) sorted | |||
return end_orig; | |||
} | |||
} | |||
not_sorted: | |||
// nth_element on range containing nth | |||
if(nth < i) | |||
{ | |||
// nth_element<C>(first, nth, i, pred); | |||
last = i; | |||
} | |||
else | |||
{ | |||
// nth_element<C>(i+1, nth, last, pred); | |||
first = ++i; | |||
} | |||
} | |||
return end_orig; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(nth_element)( | |||
Rng && rng, iterator_t<Rng> nth, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires random_access_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||
{ | |||
return (*this)( | |||
begin(rng), std::move(nth), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(nth_element) | |||
namespace cpp20 | |||
{ | |||
using ranges::nth_element; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,85 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_PARTIAL_SORT_HPP | |||
#define RANGES_V3_ALGORITHM_PARTIAL_SORT_HPP | |||
#include <functional> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/heap_algorithm.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(partial_sort) | |||
/// \brief function template \c partial_sort | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(partial_sort)( | |||
I first, I middle, S last, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires sortable<I, C, P> && random_access_iterator<I> && | |||
sentinel_for<S, I>) | |||
{ | |||
make_heap(first, middle, std::ref(pred), std::ref(proj)); | |||
auto const len = middle - first; | |||
I i = middle; | |||
for(; i != last; ++i) | |||
{ | |||
if(invoke(pred, invoke(proj, *i), invoke(proj, *first))) | |||
{ | |||
iter_swap(i, first); | |||
detail::sift_down_n( | |||
first, len, first, std::ref(pred), std::ref(proj)); | |||
} | |||
} | |||
sort_heap(first, middle, std::ref(pred), std::ref(proj)); | |||
return i; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(partial_sort)( | |||
Rng && rng, iterator_t<Rng> middle, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires sortable<iterator_t<Rng>, C, P> && random_access_range<Rng>) | |||
{ | |||
return (*this)(begin(rng), | |||
std::move(middle), | |||
end(rng), | |||
std::move(pred), | |||
std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(partial_sort) | |||
namespace cpp20 | |||
{ | |||
using ranges::partial_sort; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,121 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2013-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_PARTIAL_SORT_COPY_HPP | |||
#define RANGES_V3_ALGORITHM_PARTIAL_SORT_COPY_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/heap_algorithm.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(partial_sort_copy) | |||
/// \brief function template \c partial_sort_copy | |||
template<typename I, | |||
typename SI, | |||
typename O, | |||
typename SO, | |||
typename C = less, | |||
typename PI = identity, | |||
typename PO = identity> | |||
auto RANGES_FUN_NIEBLOID(partial_sort_copy)(I first, | |||
SI last, | |||
O out_begin, | |||
SO out_end, | |||
C pred = C{}, | |||
PI in_proj = PI{}, | |||
PO out_proj = PO{}) // | |||
->CPP_ret(O)( // | |||
requires input_iterator<I> && sentinel_for<SI, I> && | |||
random_access_iterator<O> && sentinel_for<SO, O> && | |||
indirectly_copyable<I, O> && sortable<O, C, PO> && | |||
indirect_strict_weak_order<C, projected<I, PI>, projected<O, PO>>) | |||
{ | |||
O r = out_begin; | |||
if(r != out_end) | |||
{ | |||
for(; first != last && r != out_end; ++first, ++r) | |||
*r = *first; | |||
make_heap(out_begin, r, std::ref(pred), std::ref(out_proj)); | |||
auto len = r - out_begin; | |||
for(; first != last; ++first) | |||
{ | |||
auto && x = *first; | |||
if(invoke(pred, invoke(in_proj, x), invoke(out_proj, *out_begin))) | |||
{ | |||
*out_begin = (decltype(x) &&)x; | |||
detail::sift_down_n(out_begin, | |||
len, | |||
out_begin, | |||
std::ref(pred), | |||
std::ref(out_proj)); | |||
} | |||
} | |||
sort_heap(out_begin, r, std::ref(pred), std::ref(out_proj)); | |||
} | |||
return r; | |||
} | |||
/// \overload | |||
template<typename InRng, | |||
typename OutRng, | |||
typename C = less, | |||
typename PI = identity, | |||
typename PO = identity> | |||
auto RANGES_FUN_NIEBLOID(partial_sort_copy)(InRng && in_rng, | |||
OutRng && out_rng, | |||
C pred = C{}, | |||
PI in_proj = PI{}, | |||
PO out_proj = PO{}) // | |||
->CPP_ret(safe_iterator_t<OutRng>)( // | |||
requires input_range<InRng> && random_access_range<OutRng> && | |||
indirectly_copyable<iterator_t<InRng>, iterator_t<OutRng>> && | |||
sortable<iterator_t<OutRng>, C, PO> && | |||
indirect_strict_weak_order<C, | |||
projected<iterator_t<InRng>, PI>, | |||
projected<iterator_t<OutRng>, PO>>) | |||
{ | |||
return (*this)(begin(in_rng), | |||
end(in_rng), | |||
begin(out_rng), | |||
end(out_rng), | |||
std::move(pred), | |||
std::move(in_proj), | |||
std::move(out_proj)); | |||
} | |||
RANGES_END_NIEBLOID(partial_sort_copy) | |||
namespace cpp20 | |||
{ | |||
using ranges::partial_sort_copy; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,136 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
//===-------------------------- algorithm ---------------------------------===// | |||
// | |||
// The LLVM Compiler Infrastructure | |||
// | |||
// This file is dual licensed under the MIT and the University of Illinois Open | |||
// Source Licenses. See LICENSE.TXT for details. | |||
// | |||
//===----------------------------------------------------------------------===// | |||
#ifndef RANGES_V3_ALGORITHM_PARTITION_HPP | |||
#define RANGES_V3_ALGORITHM_PARTITION_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
#include <range/v3/utility/swap.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
/// \cond | |||
namespace detail | |||
{ | |||
template<typename I, typename S, typename C, typename P> | |||
I partition_impl(I first, S last, C pred, P proj, detail::forward_iterator_tag_) | |||
{ | |||
while(true) | |||
{ | |||
if(first == last) | |||
return first; | |||
if(!invoke(pred, invoke(proj, *first))) | |||
break; | |||
++first; | |||
} | |||
for(I p = first; ++p != last;) | |||
{ | |||
if(invoke(pred, invoke(proj, *p))) | |||
{ | |||
ranges::iter_swap(first, p); | |||
++first; | |||
} | |||
} | |||
return first; | |||
} | |||
template<typename I, typename S, typename C, typename P> | |||
I partition_impl(I first, S end_, C pred, P proj, | |||
detail::bidirectional_iterator_tag_) | |||
{ | |||
I last = ranges::next(first, end_); | |||
while(true) | |||
{ | |||
while(true) | |||
{ | |||
if(first == last) | |||
return first; | |||
if(!invoke(pred, invoke(proj, *first))) | |||
break; | |||
++first; | |||
} | |||
do | |||
{ | |||
if(first == --last) | |||
return first; | |||
} while(!invoke(pred, invoke(proj, *last))); | |||
ranges::iter_swap(first, last); | |||
++first; | |||
} | |||
} | |||
} // namespace detail | |||
/// \endcond | |||
RANGES_BEGIN_NIEBLOID(partition) | |||
/// \brief function template \c partition | |||
template<typename I, typename S, typename C, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(partition)(I first, S last, C pred, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires permutable<I> && sentinel_for<S, I> && | |||
indirect_unary_predicate<C, projected<I, P>>) | |||
{ | |||
return detail::partition_impl(std::move(first), | |||
std::move(last), | |||
std::move(pred), | |||
std::move(proj), | |||
iterator_tag_of<I>()); | |||
} | |||
/// \overload | |||
template<typename Rng, typename C, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(partition)(Rng && rng, C pred, P proj = P{}) // | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires forward_range<Rng> && permutable<iterator_t<Rng>> && | |||
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return detail::partition_impl(begin(rng), | |||
end(rng), | |||
std::move(pred), | |||
std::move(proj), | |||
iterator_tag_of<iterator_t<Rng>>()); | |||
} | |||
RANGES_END_NIEBLOID(partition) | |||
namespace cpp20 | |||
{ | |||
using ranges::partition; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,107 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_PARTITION_COPY_HPP | |||
#define RANGES_V3_ALGORITHM_PARTITION_COPY_HPP | |||
#include <tuple> | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename O0, typename O1> | |||
using partition_copy_result = detail::in_out1_out2_result<I, O0, O1>; | |||
RANGES_BEGIN_NIEBLOID(partition_copy) | |||
/// \brief function template \c partition_copy | |||
template<typename I, | |||
typename S, | |||
typename O0, | |||
typename O1, | |||
typename C, | |||
typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(partition_copy)( | |||
I first, S last, O0 o0, O1 o1, C pred, P proj = P{}) | |||
->CPP_ret(partition_copy_result<I, O0, O1>)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
weakly_incrementable<O0> && weakly_incrementable<O1> && | |||
indirectly_copyable<I, O0> && indirectly_copyable<I, O1> && | |||
indirect_unary_predicate<C, projected<I, P>>) | |||
{ | |||
for(; first != last; ++first) | |||
{ | |||
auto && x = *first; | |||
if(invoke(pred, invoke(proj, x))) | |||
{ | |||
*o0 = (decltype(x) &&)x; | |||
++o0; | |||
} | |||
else | |||
{ | |||
*o1 = (decltype(x) &&)x; | |||
++o1; | |||
} | |||
} | |||
return {first, o0, o1}; | |||
} | |||
/// \overload | |||
template<typename Rng, | |||
typename O0, | |||
typename O1, | |||
typename C, | |||
typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(partition_copy)( | |||
Rng && rng, O0 o0, O1 o1, C pred, P proj = P{}) // | |||
->CPP_ret(partition_copy_result<safe_iterator_t<Rng>, O0, O1>)( // | |||
requires input_range<Rng> && weakly_incrementable<O0> && | |||
weakly_incrementable<O1> && indirectly_copyable<iterator_t<Rng>, O0> && | |||
indirectly_copyable<iterator_t<Rng>, O1> && | |||
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), | |||
end(rng), | |||
std::move(o0), | |||
std::move(o1), | |||
std::move(pred), | |||
std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(partition_copy) | |||
namespace cpp20 | |||
{ | |||
using ranges::partition_copy; | |||
using ranges::partition_copy_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,106 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// Copyright Casey Carter 2016 | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
//===-------------------------- algorithm ---------------------------------===// | |||
// | |||
// The LLVM Compiler Infrastructure | |||
// | |||
// This file is dual licensed under the MIT and the University of Illinois Open | |||
// Source Licenses. See LICENSE.TXT for details. | |||
// | |||
//===----------------------------------------------------------------------===// | |||
#ifndef RANGES_V3_ALGORITHM_PARTITION_POINT_HPP | |||
#define RANGES_V3_ALGORITHM_PARTITION_POINT_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/aux_/partition_point_n.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(partition_point) | |||
/// \brief function template \c partition_point | |||
template<typename I, typename S, typename C, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(partition_point)( | |||
I first, S last, C pred, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires forward_iterator<I> && sentinel_for<S, I> && | |||
indirect_unary_predicate<C, projected<I, P>>) | |||
{ | |||
if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S, I>)) | |||
{ | |||
auto len = distance(first, std::move(last)); | |||
return aux::partition_point_n( | |||
std::move(first), len, std::move(pred), std::move(proj)); | |||
} | |||
// Probe exponentially for either last-of-range or an iterator | |||
// that is past the partition point (i.e., does not satisfy pred). | |||
auto len = iter_difference_t<I>{1}; | |||
while(true) | |||
{ | |||
auto mid = first; | |||
auto d = advance(mid, len, last); | |||
if(mid == last || !invoke(pred, invoke(proj, *mid))) | |||
{ | |||
len -= d; | |||
return aux::partition_point_n( | |||
std::move(first), len, std::ref(pred), std::ref(proj)); | |||
} | |||
first = std::move(mid); | |||
len *= 2; | |||
} | |||
} | |||
/// \overload | |||
template<typename Rng, typename C, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(partition_point)(Rng && rng, C pred, P proj = P{}) // | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires forward_range<Rng> && | |||
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
if(RANGES_CONSTEXPR_IF(sized_range<Rng>)) | |||
{ | |||
auto len = distance(rng); | |||
return aux::partition_point_n( | |||
begin(rng), len, std::move(pred), std::move(proj)); | |||
} | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(partition_point) | |||
namespace cpp20 | |||
{ | |||
using ranges::partition_point; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,369 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
//===-------------------------- algorithm ---------------------------------===// | |||
// | |||
// The LLVM Compiler Infrastructure | |||
// | |||
// This file is dual licensed under the MIT and the University of Illinois Open | |||
// Source Licenses. See LICENSE.TXT for details. | |||
// | |||
//===----------------------------------------------------------------------===// | |||
#ifndef RANGES_V3_ALGORITHM_PERMUTATION_HPP | |||
#define RANGES_V3_ALGORITHM_PERMUTATION_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/reverse.hpp> | |||
#include <range/v3/functional/comparisons.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
#include <range/v3/utility/swap.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
/// \cond | |||
namespace detail | |||
{ | |||
template<typename I1, typename S1, typename I2, typename S2, typename C, | |||
typename P1, typename P2> | |||
bool is_permutation_impl(I1 begin1, S1 end1, I2 begin2, S2 end2, C pred, P1 proj1, | |||
P2 proj2) | |||
{ | |||
// shorten sequences as much as possible by lopping off any equal parts | |||
for(; begin1 != end1 && begin2 != end2; ++begin1, ++begin2) | |||
if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2))) | |||
goto not_done; | |||
return begin1 == end1 && begin2 == end2; | |||
not_done: | |||
// begin1 != end1 && begin2 != end2 && *begin1 != *begin2 | |||
auto l1 = distance(begin1, end1); | |||
auto l2 = distance(begin2, end2); | |||
if(l1 != l2) | |||
return false; | |||
// For each element in [f1, l1) see if there are the same number of | |||
// equal elements in [f2, l2) | |||
for(I1 i = begin1; i != end1; ++i) | |||
{ | |||
// Have we already counted the number of *i in [f1, l1)? | |||
for(I1 j = begin1; j != i; ++j) | |||
if(invoke(pred, invoke(proj1, *j), invoke(proj1, *i))) | |||
goto next_iter; | |||
{ | |||
// Count number of *i in [f2, l2) | |||
iter_difference_t<I2> c2 = 0; | |||
for(I2 j = begin2; j != end2; ++j) | |||
if(invoke(pred, invoke(proj1, *i), invoke(proj2, *j))) | |||
++c2; | |||
if(c2 == 0) | |||
return false; | |||
// Count number of *i in [i, l1) (we can start with 1) | |||
iter_difference_t<I1> c1 = 1; | |||
for(I1 j = next(i); j != end1; ++j) | |||
if(invoke(pred, invoke(proj1, *i), invoke(proj1, *j))) | |||
++c1; | |||
if(c1 != c2) | |||
return false; | |||
} | |||
next_iter:; | |||
} | |||
return true; | |||
} | |||
} // namespace detail | |||
/// \endcond | |||
RANGES_BEGIN_NIEBLOID(is_permutation) | |||
/// \brief function template \c is_permutation | |||
template<typename I1, | |||
typename S1, | |||
typename I2, | |||
typename C = equal_to, | |||
typename P1 = identity, | |||
typename P2 = identity> | |||
RANGES_DEPRECATED( | |||
"Use the variant of ranges::is_permutation that takes an upper bound " | |||
"for both sequences") | |||
auto RANGES_FUN_NIEBLOID(is_permutation)(I1 begin1, | |||
S1 end1, | |||
I2 begin2, | |||
C pred = C{}, | |||
P1 proj1 = P1{}, | |||
P2 proj2 = P2{}) // | |||
->CPP_ret(bool)( // | |||
requires forward_iterator<I1> && sentinel_for<S1, I1> && | |||
forward_iterator<I2> && indirectly_comparable<I1, I2, C, P1, P2>) | |||
{ | |||
// shorten sequences as much as possible by lopping off any equal parts | |||
for(; begin1 != end1; ++begin1, ++begin2) | |||
if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2))) | |||
goto not_done; | |||
return true; | |||
not_done: | |||
// begin1 != end1 && *begin1 != *begin2 | |||
auto l1 = distance(begin1, end1); | |||
if(l1 == 1) | |||
return false; | |||
I2 end2 = next(begin2, l1); | |||
// For each element in [f1, l1) see if there are the same number of | |||
// equal elements in [f2, l2) | |||
for(I1 i = begin1; i != end1; ++i) | |||
{ | |||
// Have we already counted the number of *i in [f1, l1)? | |||
for(I1 j = begin1; j != i; ++j) | |||
if(invoke(pred, invoke(proj1, *j), invoke(proj1, *i))) | |||
goto next_iter; | |||
{ | |||
// Count number of *i in [f2, l2) | |||
iter_difference_t<I2> c2 = 0; | |||
for(I2 j = begin2; j != end2; ++j) | |||
if(invoke(pred, invoke(proj1, *i), invoke(proj2, *j))) | |||
++c2; | |||
if(c2 == 0) | |||
return false; | |||
// Count number of *i in [i, l1) (we can start with 1) | |||
iter_difference_t<I1> c1 = 1; | |||
for(I1 j = next(i); j != end1; ++j) | |||
if(invoke(pred, invoke(proj1, *i), invoke(proj1, *j))) | |||
++c1; | |||
if(c1 != c2) | |||
return false; | |||
} | |||
next_iter:; | |||
} | |||
return true; | |||
} | |||
/// \overload | |||
template<typename I1, | |||
typename S1, | |||
typename I2, | |||
typename S2, | |||
typename C = equal_to, | |||
typename P1 = identity, | |||
typename P2 = identity> | |||
auto RANGES_FUN_NIEBLOID(is_permutation)(I1 begin1, | |||
S1 end1, | |||
I2 begin2, | |||
S2 end2, | |||
C pred = C{}, | |||
P1 proj1 = P1{}, | |||
P2 proj2 = P2{}) // | |||
->CPP_ret(bool)( // | |||
requires forward_iterator<I1> && sentinel_for<S1, I1> && | |||
forward_iterator<I2> && sentinel_for<S2, I2> && | |||
indirectly_comparable<I1, I2, C, P1, P2>) | |||
{ | |||
if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S1, I1> && | |||
sized_sentinel_for<S2, I2>)) | |||
{ | |||
RANGES_DIAGNOSTIC_PUSH | |||
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS | |||
return distance(begin1, end1) == distance(begin2, end2) && | |||
(*this)(std::move(begin1), | |||
std::move(end1), | |||
std::move(begin2), | |||
std::move(pred), | |||
std::move(proj1), | |||
std::move(proj2)); | |||
RANGES_DIAGNOSTIC_POP | |||
} | |||
return detail::is_permutation_impl(std::move(begin1), | |||
std::move(end1), | |||
std::move(begin2), | |||
std::move(end2), | |||
std::move(pred), | |||
std::move(proj1), | |||
std::move(proj2)); | |||
} | |||
/// \overload | |||
template<typename Rng1, | |||
typename I2Ref, | |||
typename C = equal_to, | |||
typename P1 = identity, | |||
typename P2 = identity> | |||
RANGES_DEPRECATED( | |||
"Use the variant of ranges::is_permutation that takes an upper bound " | |||
"for both sequences") | |||
auto RANGES_FUN_NIEBLOID(is_permutation)(Rng1 && rng1, | |||
I2Ref && begin2, | |||
C pred = C{}, | |||
P1 proj1 = P1{}, | |||
P2 proj2 = P2{}) // | |||
->CPP_ret(bool)( // | |||
requires forward_range<Rng1> && forward_iterator<uncvref_t<I2Ref>> && | |||
indirectly_comparable<iterator_t<Rng1>, uncvref_t<I2Ref>, C, P1, P2>) | |||
{ | |||
RANGES_DIAGNOSTIC_PUSH | |||
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS | |||
return (*this)(begin(rng1), | |||
end(rng1), | |||
(I2Ref &&) begin2, | |||
std::move(pred), | |||
std::move(proj1), | |||
std::move(proj2)); | |||
RANGES_DIAGNOSTIC_POP | |||
} | |||
/// \overload | |||
template<typename Rng1, | |||
typename Rng2, | |||
typename C = equal_to, | |||
typename P1 = identity, | |||
typename P2 = identity> | |||
auto RANGES_FUN_NIEBLOID(is_permutation)( | |||
Rng1 && rng1, Rng2 && rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) // | |||
->CPP_ret(bool)( // | |||
requires forward_range<Rng1> && forward_range<Rng2> && | |||
indirectly_comparable<iterator_t<Rng1>, iterator_t<Rng2>, C, P1, P2>) | |||
{ | |||
if(RANGES_CONSTEXPR_IF(sized_range<Rng1> && sized_range<Rng2>)) | |||
{ | |||
RANGES_DIAGNOSTIC_PUSH | |||
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS | |||
return distance(rng1) == distance(rng2) && (*this)(begin(rng1), | |||
end(rng1), | |||
begin(rng2), | |||
std::move(pred), | |||
std::move(proj1), | |||
std::move(proj2)); | |||
RANGES_DIAGNOSTIC_POP | |||
} | |||
return detail::is_permutation_impl(begin(rng1), | |||
end(rng1), | |||
begin(rng2), | |||
end(rng2), | |||
std::move(pred), | |||
std::move(proj1), | |||
std::move(proj2)); | |||
} | |||
RANGES_END_NIEBLOID(is_permutation) | |||
RANGES_BEGIN_NIEBLOID(next_permutation) | |||
/// \brief function template \c next_permutation | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(next_permutation)( | |||
I first, S end_, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires bidirectional_iterator<I> && sentinel_for<S, I> && | |||
sortable<I, C, P>) | |||
{ | |||
if(first == end_) | |||
return false; | |||
I last = ranges::next(first, end_), i = last; | |||
if(first == --i) | |||
return false; | |||
while(true) | |||
{ | |||
I ip1 = i; | |||
if(invoke(pred, invoke(proj, *--i), invoke(proj, *ip1))) | |||
{ | |||
I j = last; | |||
while(!invoke(pred, invoke(proj, *i), invoke(proj, *--j))) | |||
; | |||
ranges::iter_swap(i, j); | |||
ranges::reverse(ip1, last); | |||
return true; | |||
} | |||
if(i == first) | |||
{ | |||
ranges::reverse(first, last); | |||
return false; | |||
} | |||
} | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(next_permutation)( | |||
Rng && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires bidirectional_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(next_permutation) | |||
RANGES_BEGIN_NIEBLOID(prev_permutation) | |||
/// \brief function template \c prev_permutation | |||
template<typename I, typename S, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(prev_permutation)( | |||
I first, S end_, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires bidirectional_iterator<I> && sentinel_for<S, I> && | |||
sortable<I, C, P>) | |||
{ | |||
if(first == end_) | |||
return false; | |||
I last = ranges::next(first, end_), i = last; | |||
if(first == --i) | |||
return false; | |||
while(true) | |||
{ | |||
I ip1 = i; | |||
if(invoke(pred, invoke(proj, *ip1), invoke(proj, *--i))) | |||
{ | |||
I j = last; | |||
while(!invoke(pred, invoke(proj, *--j), invoke(proj, *i))) | |||
; | |||
ranges::iter_swap(i, j); | |||
ranges::reverse(ip1, last); | |||
return true; | |||
} | |||
if(i == first) | |||
{ | |||
ranges::reverse(first, last); | |||
return false; | |||
} | |||
} | |||
} | |||
/// \overload | |||
template<typename Rng, typename C = less, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(prev_permutation)( | |||
Rng && rng, C pred = C{}, P proj = P{}) // | |||
->CPP_ret(bool)( // | |||
requires bidirectional_range<Rng> && sortable<iterator_t<Rng>, C, P>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(prev_permutation) | |||
namespace cpp20 | |||
{ | |||
using ranges::is_permutation; | |||
using ranges::next_permutation; | |||
using ranges::prev_permutation; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,79 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_REMOVE_HPP | |||
#define RANGES_V3_ALGORITHM_REMOVE_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/find.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(remove) | |||
/// \brief function template \c remove | |||
template<typename I, typename S, typename T, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(remove)(I first, S last, T const & val, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires permutable<I> && sentinel_for<S, I> && | |||
indirect_relation<equal_to, projected<I, P>, T const *>) | |||
{ | |||
first = find(std::move(first), last, val, std::ref(proj)); | |||
if(first != last) | |||
{ | |||
for(I i = next(first); i != last; ++i) | |||
{ | |||
if(!(invoke(proj, *i) == val)) | |||
{ | |||
*first = iter_move(i); | |||
++first; | |||
} | |||
} | |||
} | |||
return first; | |||
} | |||
/// \overload | |||
template<typename Rng, typename T, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(remove)(Rng && rng, T const & val, P proj = P{}) | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires forward_range<Rng> && permutable<iterator_t<Rng>> && | |||
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, T const *>) | |||
{ | |||
return (*this)(begin(rng), end(rng), val, std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(remove) | |||
namespace cpp20 | |||
{ | |||
using ranges::remove; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,84 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_REMOVE_COPY_HPP | |||
#define RANGES_V3_ALGORITHM_REMOVE_COPY_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename O> | |||
using remove_copy_result = detail::in_out_result<I, O>; | |||
RANGES_BEGIN_NIEBLOID(remove_copy) | |||
/// \brief function template \c remove_copy | |||
template<typename I, typename S, typename O, typename T, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(remove_copy)( | |||
I first, S last, O out, T const & val, P proj = P{}) // | |||
->CPP_ret(remove_copy_result<I, O>)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
weakly_incrementable<O> && | |||
indirect_relation<equal_to, projected<I, P>, T const *> && | |||
indirectly_copyable<I, O>) | |||
{ | |||
for(; first != last; ++first) | |||
{ | |||
auto && x = *first; | |||
if(!(invoke(proj, x) == val)) | |||
{ | |||
*out = (decltype(x) &&)x; | |||
++out; | |||
} | |||
} | |||
return {first, out}; | |||
} | |||
/// \overload | |||
template<typename Rng, typename O, typename T, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(remove_copy)( | |||
Rng && rng, O out, T const & val, P proj = P{}) // | |||
->CPP_ret(remove_copy_result<safe_iterator_t<Rng>, O>)( // | |||
requires input_range<Rng> && weakly_incrementable<O> && | |||
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, T const *> && | |||
indirectly_copyable<iterator_t<Rng>, O>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(out), val, std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(remove_copy) | |||
namespace cpp20 | |||
{ | |||
using ranges::remove_copy; | |||
using ranges::remove_copy_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,84 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_REMOVE_COPY_IF_HPP | |||
#define RANGES_V3_ALGORITHM_REMOVE_COPY_IF_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename O> | |||
using remove_copy_if_result = detail::in_out_result<I, O>; | |||
RANGES_BEGIN_NIEBLOID(remove_copy_if) | |||
/// \brief function template \c remove_copy_if | |||
template<typename I, typename S, typename O, typename C, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(remove_copy_if)( | |||
I first, S last, O out, C pred, P proj = P{}) // | |||
->CPP_ret(remove_copy_if_result<I, O>)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
weakly_incrementable<O> && indirect_unary_predicate<C, projected<I, P>> && | |||
indirectly_copyable<I, O>) | |||
{ | |||
for(; first != last; ++first) | |||
{ | |||
auto && x = *first; | |||
if(!(invoke(pred, invoke(proj, x)))) | |||
{ | |||
*out = (decltype(x) &&)x; | |||
++out; | |||
} | |||
} | |||
return {first, out}; | |||
} | |||
/// \overload | |||
template<typename Rng, typename O, typename C, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(remove_copy_if)( | |||
Rng && rng, O out, C pred, P proj = P{}) // | |||
->CPP_ret(remove_copy_if_result<safe_iterator_t<Rng>, O>)( // | |||
requires input_range<Rng> && weakly_incrementable<O> && | |||
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>> && | |||
indirectly_copyable<iterator_t<Rng>, O>) | |||
{ | |||
return (*this)( | |||
begin(rng), end(rng), std::move(out), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(remove_copy_if) | |||
namespace cpp20 | |||
{ | |||
using ranges::remove_copy_if; | |||
using ranges::remove_copy_if_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,79 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_REMOVE_IF_HPP | |||
#define RANGES_V3_ALGORITHM_REMOVE_IF_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/find_if.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/operations.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(remove_if) | |||
/// \brief function template \c remove_if | |||
template<typename I, typename S, typename C, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(remove_if)(I first, S last, C pred, P proj = P{}) // | |||
->CPP_ret(I)( // | |||
requires permutable<I> && sentinel_for<S, I> && | |||
indirect_unary_predicate<C, projected<I, P>>) | |||
{ | |||
first = find_if(std::move(first), last, std::ref(pred), std::ref(proj)); | |||
if(first != last) | |||
{ | |||
for(I i = next(first); i != last; ++i) | |||
{ | |||
if(!(invoke(pred, invoke(proj, *i)))) | |||
{ | |||
*first = iter_move(i); | |||
++first; | |||
} | |||
} | |||
} | |||
return first; | |||
} | |||
/// \overload | |||
template<typename Rng, typename C, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(remove_if)(Rng && rng, C pred, P proj = P{}) // | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires forward_range<Rng> && permutable<iterator_t<Rng>> && | |||
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>>) | |||
{ | |||
return (*this)(begin(rng), end(rng), std::move(pred), std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(remove_if) | |||
namespace cpp20 | |||
{ | |||
using ranges::remove_if; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,71 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_REPLACE_HPP | |||
#define RANGES_V3_ALGORITHM_REPLACE_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
RANGES_BEGIN_NIEBLOID(replace) | |||
/// \brief function template \c replace | |||
template<typename I, typename S, typename T1, typename T2, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(replace)( | |||
I first, S last, T1 const & old_value, T2 const & new_value, P proj = {}) // | |||
->CPP_ret(I)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
writable<I, T2 const &> && | |||
indirect_relation<equal_to, projected<I, P>, T1 const *>) | |||
{ | |||
for(; first != last; ++first) | |||
if(invoke(proj, *first) == old_value) | |||
*first = new_value; | |||
return first; | |||
} | |||
/// \overload | |||
template<typename Rng, typename T1, typename T2, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(replace)( | |||
Rng && rng, T1 const & old_value, T2 const & new_value, P proj = {}) // | |||
->CPP_ret(safe_iterator_t<Rng>)( // | |||
requires input_range<Rng> && writable<iterator_t<Rng>, T2 const &> && | |||
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, T1 const *>) | |||
{ | |||
return (*this)(begin(rng), end(rng), old_value, new_value, std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(replace) | |||
namespace cpp20 | |||
{ | |||
using ranges::replace; | |||
} | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,100 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_REPLACE_COPY_HPP | |||
#define RANGES_V3_ALGORITHM_REPLACE_COPY_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename O> | |||
using replace_copy_result = detail::in_out_result<I, O>; | |||
RANGES_BEGIN_NIEBLOID(replace_copy) | |||
/// \brief function template \c replace_copy | |||
template<typename I, | |||
typename S, | |||
typename O, | |||
typename T1, | |||
typename T2, | |||
typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(replace_copy)(I first, | |||
S last, | |||
O out, | |||
T1 const & old_value, | |||
T2 const & new_value, | |||
P proj = {}) // | |||
->CPP_ret(replace_copy_result<I, O>)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
output_iterator<O, T2 const &> && indirectly_copyable<I, O> && | |||
indirect_relation<equal_to, projected<I, P>, T1 const *>) | |||
{ | |||
for(; first != last; ++first, ++out) | |||
{ | |||
auto && x = *first; | |||
if(invoke(proj, x) == old_value) | |||
*out = new_value; | |||
else | |||
*out = (decltype(x) &&)x; | |||
} | |||
return {first, out}; | |||
} | |||
/// \overload | |||
template<typename Rng, | |||
typename O, | |||
typename T1, | |||
typename T2, | |||
typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(replace_copy)( | |||
Rng && rng, O out, T1 const & old_value, T2 const & new_value, P proj = {}) // | |||
->CPP_ret(replace_copy_result<safe_iterator_t<Rng>, O>)( // | |||
requires input_range<Rng> && output_iterator<O, T2 const &> && | |||
indirectly_copyable<iterator_t<Rng>, O> && | |||
indirect_relation<equal_to, projected<iterator_t<Rng>, P>, T1 const *>) | |||
{ | |||
return (*this)(begin(rng), | |||
end(rng), | |||
std::move(out), | |||
old_value, | |||
new_value, | |||
std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(replace_copy) | |||
namespace cpp20 | |||
{ | |||
using ranges::replace_copy; | |||
using ranges::replace_copy_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |
@@ -0,0 +1,92 @@ | |||
/// \file | |||
// Range v3 library | |||
// | |||
// Copyright Eric Niebler 2014-present | |||
// | |||
// Use, modification and distribution is subject to 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) | |||
// | |||
// Project home: https://github.com/ericniebler/range-v3 | |||
// | |||
#ifndef RANGES_V3_ALGORITHM_REPLACE_COPY_IF_HPP | |||
#define RANGES_V3_ALGORITHM_REPLACE_COPY_IF_HPP | |||
#include <meta/meta.hpp> | |||
#include <range/v3/range_fwd.hpp> | |||
#include <range/v3/algorithm/result_types.hpp> | |||
#include <range/v3/functional/identity.hpp> | |||
#include <range/v3/functional/invoke.hpp> | |||
#include <range/v3/iterator/concepts.hpp> | |||
#include <range/v3/iterator/traits.hpp> | |||
#include <range/v3/range/access.hpp> | |||
#include <range/v3/range/concepts.hpp> | |||
#include <range/v3/range/dangling.hpp> | |||
#include <range/v3/range/traits.hpp> | |||
#include <range/v3/utility/static_const.hpp> | |||
namespace ranges | |||
{ | |||
/// \addtogroup group-algorithms | |||
/// @{ | |||
template<typename I, typename O> | |||
using replace_copy_if_result = detail::in_out_result<I, O>; | |||
RANGES_BEGIN_NIEBLOID(replace_copy_if) | |||
/// \brief function template \c replace_copy_if | |||
template<typename I, | |||
typename S, | |||
typename O, | |||
typename C, | |||
typename T, | |||
typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(replace_copy_if)( | |||
I first, S last, O out, C pred, T const & new_value, P proj = {}) // | |||
->CPP_ret(replace_copy_if_result<I, O>)( // | |||
requires input_iterator<I> && sentinel_for<S, I> && | |||
output_iterator<O, T const &> && | |||
indirect_unary_predicate<C, projected<I, P>> && indirectly_copyable<I, O>) | |||
{ | |||
for(; first != last; ++first, ++out) | |||
{ | |||
auto && x = *first; | |||
if(invoke(pred, invoke(proj, x))) | |||
*out = new_value; | |||
else | |||
*out = (decltype(x) &&)x; | |||
} | |||
return {first, out}; | |||
} | |||
/// \overload | |||
template<typename Rng, typename O, typename C, typename T, typename P = identity> | |||
auto RANGES_FUN_NIEBLOID(replace_copy_if)( | |||
Rng && rng, O out, C pred, T const & new_value, P proj = {}) // | |||
->CPP_ret(replace_copy_if_result<safe_iterator_t<Rng>, O>)( // | |||
requires input_range<Rng> && output_iterator<O, T const &> && | |||
indirect_unary_predicate<C, projected<iterator_t<Rng>, P>> && | |||
indirectly_copyable<iterator_t<Rng>, O>) | |||
{ | |||
return (*this)(begin(rng), | |||
end(rng), | |||
std::move(out), | |||
std::move(pred), | |||
new_value, | |||
std::move(proj)); | |||
} | |||
RANGES_END_NIEBLOID(replace_copy_if) | |||
namespace cpp20 | |||
{ | |||
using ranges::replace_copy_if; | |||
using ranges::replace_copy_if_result; | |||
} // namespace cpp20 | |||
/// @} | |||
} // namespace ranges | |||
#endif // include guard |