init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
allhaileris
2026-02-16 15:50:16 +03:00
commit afb81b8278
13816 changed files with 3689732 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
/// \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_FUNCTIONAL_ARITHMETIC_HPP
#define RANGES_V3_FUNCTIONAL_ARITHMETIC_HPP
#include <concepts/concepts.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
struct plus
{
template<typename T, typename U>
constexpr auto operator()(T && t, U && u) const -> decltype((T &&) t + (U &&) u)
{
return (T &&) t + (U &&) u;
}
using is_transparent = void;
};
struct minus
{
template<typename T, typename U>
constexpr auto operator()(T && t, U && u) const -> decltype((T &&) t - (U &&) u)
{
return (T &&) t - (U &&) u;
}
using is_transparent = void;
};
struct multiplies
{
template<typename T, typename U>
constexpr auto operator()(T && t, U && u) const -> decltype((T &&) t * (U &&) u)
{
return (T &&) t * (U &&) u;
}
using is_transparent = void;
};
struct bitwise_or
{
template<typename T, typename U>
constexpr auto operator()(T && t, U && u) const -> decltype((T &&) t | (U &&) u)
{
return (T &&) t | (U &&) u;
}
using is_transparent = void;
};
template<typename T>
struct convert_to
{
// clang-format off
template<typename U>
constexpr auto CPP_auto_fun(operator())(U &&u)(const)
(
return static_cast<T>((U &&) u)
)
// clang-format on
};
template<typename T>
struct coerce
{
constexpr T & operator()(T & t) const
{
return t;
}
/// \overload
constexpr T const & operator()(T const & t) const
{
return t;
}
/// \overload
constexpr T operator()(T && t) const
{
return (T &&) t;
}
T operator()(T const &&) const = delete;
};
template<typename T>
struct coerce<T const> : coerce<T>
{};
template<typename T>
struct coerce<T &> : coerce<T>
{};
template<typename T>
struct coerce<T &&> : coerce<T>
{};
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -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_FUNCTIONAL_BIND_HPP
#define RANGES_V3_FUNCTIONAL_BIND_HPP
#include <functional>
#include <type_traits>
#include <meta/meta.hpp>
#include <concepts/concepts.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
template<typename T,
typename U = meta::if_<
std::is_lvalue_reference<T>,
std::reference_wrapper<meta::_t<std::remove_reference<T>>>, T &&>>
U bind_forward(meta::_t<std::remove_reference<T>> & t) noexcept
{
return static_cast<U>(t);
}
template<typename T>
T && bind_forward(meta::_t<std::remove_reference<T>> && t) noexcept
{
// This is to catch way sketchy stuff like: forward<int const &>(42)
static_assert(!std::is_lvalue_reference<T>::value, "You didn't just do that!");
return static_cast<T &&>(t);
}
template<typename T>
struct bind_element
: meta::if_c<RANGES_IS_SAME(detail::decay_t<T>, T), meta::id<T>,
bind_element<detail::decay_t<T>>>
{};
template<typename T>
struct bind_element<std::reference_wrapper<T>>
{
using type = T &;
};
template<typename T>
struct bind_element<reference_wrapper<T>>
{
using type = typename reference_wrapper<T>::reference;
};
template<typename T>
using bind_element_t = meta::_t<bind_element<T>>;
template<typename Bind>
struct protector
{
private:
Bind bind_;
public:
protector() = default;
protector(Bind b)
: bind_(std::move(b))
{}
// clang-format off
template<typename...Ts>
auto CPP_auto_fun(operator())(Ts &&...ts)
(
return bind_(static_cast<Ts &&>(ts)...)
)
/// \overload
template<typename...Ts>
auto CPP_auto_fun(operator())(Ts &&...ts) (const)
(
return bind_(static_cast<Ts &&>(ts)...)
)
// clang-format on
};
struct protect_fn
{
template(typename F)(
requires std::is_bind_expression<uncvref_t<F>>::value) //
protector<uncvref_t<F>> operator()(F && f) const
{
return {static_cast<F &&>(f)};
}
/// \overload
template(typename F)(
requires (!std::is_bind_expression<uncvref_t<F>>::value)) //
F operator()(F && f) const
{
return static_cast<F &&>(f);
}
};
/// Protect a callable so that it can be safely used in a bind expression without
/// accidentally becoming a "nested" bind.
/// \ingroup group-functional
/// \sa `protect_fn`
RANGES_INLINE_VARIABLE(protect_fn, protect)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,192 @@
/// \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_DETAIL_BIND_BACK_HPP
#define RANGES_V3_DETAIL_BIND_BACK_HPP
#include <tuple>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/utility/tuple_algorithm.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
// bind_back like std::bind_front has no special treatment for nested
// bind-expressions or reference_wrappers; there is no need to wrap
// Callables with ranges::protect.
namespace detail
{
template<typename Fn, typename... Args>
struct bind_back_fn_
{
using tuple_t = std::tuple<Fn, Args...>;
tuple_t fn_args_;
template<typename... CallArgs>
constexpr invoke_result_t<Fn, CallArgs..., Args...> //
operator()(CallArgs &&... cargs) &&
noexcept(is_nothrow_invocable_v<Fn, CallArgs..., Args...>)
{
return tuple_apply(
[&](auto && fn, auto &&... args) -> decltype(auto) {
return invoke((decltype(fn))fn,
(CallArgs &&) cargs...,
(decltype(args))args...);
},
(std::tuple<Fn, Args...> &&) fn_args_);
}
/// \overload
template<typename... CallArgs>
constexpr invoke_result_t<Fn &, CallArgs..., Args &...>
operator()(CallArgs &&... cargs) &
noexcept(is_nothrow_invocable_v<Fn &, CallArgs..., Args &...>)
{
return tuple_apply(
[&](auto & fn, auto &... args) -> decltype(auto) {
return invoke(fn, (CallArgs &&) cargs..., args...);
},
fn_args_);
}
/// \overload
template<typename... CallArgs>
constexpr invoke_result_t<Fn const &, CallArgs..., Args const &...>
operator()(CallArgs &&... cargs) const & //
noexcept(is_nothrow_invocable_v<Fn const &, CallArgs..., Args const &...>)
{
return tuple_apply(
[&](auto & fn, auto &... args) -> decltype(auto) {
return invoke(fn, (CallArgs &&) cargs..., args...);
},
fn_args_);
}
};
/// \cond
// Unroll a few instantiations to avoid a heavy-weight tuple instantiation
template<typename Fn, typename Arg>
struct bind_back_fn_<Fn, Arg>
{
struct tuple_t
{
Fn fn_;
Arg arg_;
};
tuple_t fn_args_;
template<typename... CallArgs>
constexpr invoke_result_t<Fn, CallArgs..., Arg> //
operator()(CallArgs &&... cargs) && //
noexcept(is_nothrow_invocable_v<Fn, CallArgs..., Arg>)
{
return invoke(
(Fn &&) fn_args_.fn_, (CallArgs &&) cargs..., (Arg &&) fn_args_.arg_);
}
template<typename... CallArgs>
constexpr invoke_result_t<Fn &, CallArgs..., Arg &> //
operator()(CallArgs &&... cargs) & //
noexcept(is_nothrow_invocable_v<Fn &, CallArgs..., Arg &>)
{
return invoke(fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg_);
}
template<typename... CallArgs>
constexpr invoke_result_t<Fn const &, CallArgs..., Arg const &> //
operator()(CallArgs &&... cargs) const & //
noexcept(is_nothrow_invocable_v<Fn const &, CallArgs..., Arg const &>)
{
return invoke(fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg_);
}
};
template<typename Fn, typename Arg0, typename Arg1>
struct bind_back_fn_<Fn, Arg0, Arg1>
{
struct tuple_t
{
Fn fn_;
Arg0 arg0_;
Arg1 arg1_;
};
tuple_t fn_args_;
template<typename... CallArgs>
constexpr invoke_result_t<Fn, CallArgs..., Arg0, Arg1> //
operator()(CallArgs &&... cargs) && //
noexcept(is_nothrow_invocable_v<Fn, CallArgs..., Arg0, Arg1>)
{
return invoke((Fn &&) fn_args_.fn_,
(CallArgs &&) cargs...,
(Arg0 &&) fn_args_.arg0_,
(Arg1 &&) fn_args_.arg1_);
}
template<typename... CallArgs>
constexpr invoke_result_t<Fn &, CallArgs..., Arg0 &, Arg1 &> //
operator()(CallArgs &&... cargs) & //
noexcept(is_nothrow_invocable_v<Fn &, CallArgs..., Arg0 &, Arg1 &>)
{
return invoke(
fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg0_, fn_args_.arg1_);
}
template<typename... CallArgs>
constexpr invoke_result_t<Fn const &, CallArgs..., Arg0 const &, Arg1 const &>
operator()(CallArgs &&... cargs) const &
noexcept(is_nothrow_invocable_v<Fn const &,
CallArgs...,
Arg0 const &,
Arg1 const &>)
{
return invoke(
fn_args_.fn_, (CallArgs &&) cargs..., fn_args_.arg0_, fn_args_.arg1_);
}
};
/// \endcond
template<typename Fn, typename... Args>
using bind_back_fn = bind_back_fn_<decay_t<Fn>, decay_t<Args>...>;
} // namespace detail
struct bind_back_fn
{
template<typename Fn, typename Arg1, typename... Args>
constexpr detail::bind_back_fn<Fn, Arg1, Args...> //
operator()(Fn && fn, Arg1 && arg1, Args &&... args) const
{
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
using T = typename detail::bind_back_fn<Fn, Arg1, Args...>::tuple_t;
return {T{(Fn &&) fn, (Arg1 &&) arg1, (Args &&) args...}};
#else
return {{(Fn &&) fn, (Arg1 &&) arg1, (Args &&) args...}};
#endif
}
};
/// \ingroup group-utility
/// \sa `bind_back_fn`
RANGES_INLINE_VARIABLE(bind_back_fn, bind_back)
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif // RANGES_V3_DETAIL_BIND_BACK_HPP

View File

@@ -0,0 +1,126 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-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_FUNCTIONAL_COMPARISONS_HPP
#define RANGES_V3_FUNCTIONAL_COMPARISONS_HPP
#include <concepts/concepts.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
struct equal_to
{
template(typename T, typename U)(
requires equality_comparable_with<T, U>)
constexpr bool operator()(T && t, U && u) const
{
return (T &&) t == (U &&) u;
}
using is_transparent = void;
};
struct not_equal_to
{
template(typename T, typename U)(
requires equality_comparable_with<T, U>)
constexpr bool operator()(T && t, U && u) const
{
return !equal_to{}((T &&) t, (U &&) u);
}
using is_transparent = void;
};
struct less
{
template(typename T, typename U)(
requires totally_ordered_with<T, U>)
constexpr bool operator()(T && t, U && u) const
{
return (T &&) t < (U &&) u;
}
using is_transparent = void;
};
struct less_equal
{
template(typename T, typename U)(
requires totally_ordered_with<T, U>)
constexpr bool operator()(T && t, U && u) const
{
return !less{}((U &&) u, (T &&) t);
}
using is_transparent = void;
};
struct greater_equal
{
template(typename T, typename U)(
requires totally_ordered_with<T, U>)
constexpr bool operator()(T && t, U && u) const
{
return !less{}((T &&) t, (U &&) u);
}
using is_transparent = void;
};
struct greater
{
template(typename T, typename U)(
requires totally_ordered_with<T, U>)
constexpr bool operator()(T && t, U && u) const
{
return less{}((U &&) u, (T &&) t);
}
using is_transparent = void;
};
using ordered_less RANGES_DEPRECATED(
"Repace uses of ranges::ordered_less with ranges::less") = less;
#if __cplusplus > 201703L && __has_include(<compare>) && \
defined(__cpp_concepts) && defined(__cpp_impl_three_way_comparison)
struct compare_three_way
{
template(typename T, typename U)(
requires three_way_comparable_with<T, U>)
constexpr auto operator()(T && t, U && u) const
-> decltype((T &&) t <=> (U &&) u)
{
return (T &&) t <=> (U &&) u;
}
using is_transparent = void;
};
#endif // __cplusplus
namespace cpp20
{
using ranges::equal_to;
using ranges::greater;
using ranges::greater_equal;
using ranges::less;
using ranges::less_equal;
using ranges::not_equal_to;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,104 @@
/// \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_FUNCTIONAL_COMPOSE_HPP
#define RANGES_V3_FUNCTIONAL_COMPOSE_HPP
#include <type_traits>
#include <utility>
#include <concepts/concepts.hpp>
#include <range/v3/detail/config.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
template<typename Second, typename First>
struct composed
{
private:
RANGES_NO_UNIQUE_ADDRESS
First first_;
RANGES_NO_UNIQUE_ADDRESS
Second second_;
// clang-format off
template<typename A, typename B, typename... Ts>
static constexpr auto //
CPP_auto_fun(do_)(A &&a, B &&b, std::false_type, Ts &&... ts)
(
return invoke((B &&) b, invoke((A &&) a, (Ts &&) ts...))
)
template<typename A, typename B, typename... Ts>
static constexpr auto CPP_auto_fun(do_)(A &&a, B &&b, std::true_type, Ts &&... ts)
(
return (invoke((A &&) a, (Ts &&) ts...), invoke((B &&) b))
)
public:
composed() = default;
// clang-format on
constexpr composed(Second second, First first)
: first_(std::move(first))
, second_(std::move(second))
{}
// clang-format off
template<typename... Ts>
constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(mutable &)
(
return composed::do_(first_,
second_,
std::is_void<invoke_result_t<First &, Ts...>>{},
(Ts &&) ts...)
)
template<typename... Ts>
constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(const &)
(
return composed::do_((First const &)first_,
(Second const &)second_,
std::is_void<invoke_result_t<First const &, Ts...>>{},
(Ts &&) ts...)
)
template<typename... Ts>
constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(mutable &&)
(
return composed::do_((First &&)first_,
(Second &&)second_,
std::is_void<invoke_result_t<First &&, Ts...>>{},
(Ts &&) ts...)
)
// clang-format on
};
struct compose_fn
{
template<typename Second, typename First>
constexpr composed<Second, First> operator()(Second second, First first) const
{
return {std::move(second), std::move(first)};
}
};
/// \ingroup group-functional
/// \sa `compose_fn`
RANGES_INLINE_VARIABLE(compose_fn, compose)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,106 @@
/// \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_FUNCTIONAL_CONCEPTS_HPP
#define RANGES_V3_FUNCTIONAL_CONCEPTS_HPP
#include <concepts/concepts.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
// clang-format off
// WORKAROUND mysterious msvc bug
#if defined(_MSC_VER) && !defined(__clang__)
/// \concept invocable
/// \brief The \c invocable concept
template<typename Fun, typename... Args>
CPP_concept invocable =
std::is_invocable_v<Fun, Args...>;
#else
/// \concept invocable_
/// \brief The \c invocable_ concept
template<typename Fun, typename... Args>
CPP_requires(invocable_,
requires(Fun && fn) //
(
invoke((Fun &&) fn, std::declval<Args>()...)
));
/// \concept invocable
/// \brief The \c invocable concept
template<typename Fun, typename... Args>
CPP_concept invocable =
CPP_requires_ref(ranges::invocable_, Fun, Args...);
#endif
/// \concept regular_invocable
/// \brief The \c regular_invocable concept
template<typename Fun, typename... Args>
CPP_concept regular_invocable =
invocable<Fun, Args...>;
// Axiom: equality_preserving(invoke(f, args...))
/// \concept predicate_
/// \brief The \c predicate_ concept
template<typename Fun, typename... Args>
CPP_requires(predicate_,
requires(Fun && fn) //
(
concepts::requires_<
convertible_to<
decltype(invoke((Fun &&) fn, std::declval<Args>()...)),
bool>>
));
/// \concept predicate
/// \brief The \c predicate concept
template<typename Fun, typename... Args>
CPP_concept predicate =
regular_invocable<Fun, Args...> &&
CPP_requires_ref(ranges::predicate_, Fun, Args...);
/// \concept relation
/// \brief The \c relation concept
template<typename R, typename T, typename U>
CPP_concept relation =
predicate<R, T, T> &&
predicate<R, U, U> &&
predicate<R, T, U> &&
predicate<R, U, T>;
/// \concept strict_weak_order
/// \brief The \c strict_weak_order concept
template<typename R, typename T, typename U>
CPP_concept strict_weak_order =
relation<R, T, U>;
// clang-format on
namespace cpp20
{
using ranges::invocable;
using ranges::predicate;
using ranges::regular_invocable;
using ranges::relation;
using ranges::strict_weak_order;
} // namespace cpp20
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,48 @@
/// \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_FUNCTIONAL_IDENTITY_HPP
#define RANGES_V3_FUNCTIONAL_IDENTITY_HPP
#include <range/v3/detail/config.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
struct identity
{
template<typename T>
constexpr T && operator()(T && t) const noexcept
{
return (T &&) t;
}
using is_transparent = void;
};
/// \cond
using ident RANGES_DEPRECATED("Replace uses of ranges::ident with ranges::identity") =
identity;
/// \endcond
namespace cpp20
{
using ranges::identity;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,100 @@
/// \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_FUNCTIONAL_INDIRECT_HPP
#define RANGES_V3_FUNCTIONAL_INDIRECT_HPP
#include <utility>
#include <concepts/concepts.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/iterator/traits.hpp>
#include <range/v3/utility/move.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
template<typename Fn>
struct indirected
{
private:
RANGES_NO_UNIQUE_ADDRESS
Fn fn_;
public:
indirected() = default;
indirected(Fn fn)
: fn_(std::move(fn))
{}
// value_type (needs no impl)
template<typename... Its>
[[noreturn]] invoke_result_t<Fn &, iter_reference_t<Its>...> //
operator()(copy_tag, Its...) const
{
RANGES_EXPECT(false);
}
// Reference
// clang-format off
template<typename... Its>
auto CPP_auto_fun(operator())(Its... its)
(
return invoke(fn_, *its...)
)
template<typename... Its>
auto CPP_auto_fun(operator())(Its... its)(const)
(
return invoke((Fn const &)fn_, *its...)
)
// Rvalue reference
template<typename... Its>
auto CPP_auto_fun(operator())(move_tag, Its... its)
(
return static_cast<
aux::move_t<invoke_result_t<Fn &, iter_reference_t<Its>...>>>(
aux::move(invoke(fn_, *its...)))
)
template<typename... Its>
auto CPP_auto_fun(operator())(move_tag, Its... its)(const)
(
return static_cast<
aux::move_t<invoke_result_t<Fn const &, iter_reference_t<Its>...>>>(
aux::move(invoke((Fn const &)fn_, *its...)))
)
// clang-format on
};
struct indirect_fn
{
template<typename Fn>
constexpr indirected<Fn> operator()(Fn fn) const
{
return indirected<Fn>{detail::move(fn)};
}
};
/// \ingroup group-functional
/// \sa `indirect_fn`
RANGES_INLINE_VARIABLE(indirect_fn, indirect)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,246 @@
/// \file
// Range v3 library
//
// Copyright Eric Niebler 2013-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_FUNCTIONAL_INVOKE_HPP
#define RANGES_V3_FUNCTIONAL_INVOKE_HPP
#include <functional>
#include <type_traits>
#include <meta/meta.hpp>
#include <concepts/concepts.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
RANGES_DIAGNOSTIC_PUSH
RANGES_DIAGNOSTIC_IGNORE_CXX17_COMPAT
RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
#ifndef RANGES_CONSTEXPR_INVOKE
#ifdef RANGES_WORKAROUND_CLANG_23135
#define RANGES_CONSTEXPR_INVOKE 0
#else
#define RANGES_CONSTEXPR_INVOKE 1
#endif
#endif
namespace ranges
{
/// \addtogroup group-functional
/// @{
/// \cond
namespace detail
{
RANGES_DIAGNOSTIC_PUSH
RANGES_DIAGNOSTIC_IGNORE_VOID_PTR_DEREFERENCE
template<typename U>
U & can_reference_(U &&);
// clang-format off
/// \concept dereferenceable_part_
/// \brief The \c dereferenceable_part_ concept
template<typename T>
CPP_requires(dereferenceable_part_,
requires(T && t) //
(
detail::can_reference_(*(T &&) t)
));
/// \concept dereferenceable_
/// \brief The \c dereferenceable_ concept
template<typename T>
CPP_concept dereferenceable_ = //
CPP_requires_ref(detail::dereferenceable_part_, T);
// clang-format on
RANGES_DIAGNOSTIC_POP
template<typename T>
RANGES_INLINE_VAR constexpr bool is_reference_wrapper_v =
meta::is<T, reference_wrapper>::value ||
meta::is<T, std::reference_wrapper>::value;
} // namespace detail
/// \endcond
template<typename T>
RANGES_INLINE_VAR constexpr bool is_reference_wrapper_v =
detail::is_reference_wrapper_v<detail::decay_t<T>>;
template<typename T>
using is_reference_wrapper = meta::bool_<is_reference_wrapper_v<T>>;
/// \cond
template<typename T>
using is_reference_wrapper_t RANGES_DEPRECATED(
"is_reference_wrapper_t is deprecated.") = meta::_t<is_reference_wrapper<T>>;
/// \endcond
struct invoke_fn
{
private:
template(typename, typename T1)(
requires detail::dereferenceable_<T1>)
static constexpr decltype(auto) coerce(T1 && t1, long)
noexcept(noexcept(*static_cast<T1 &&>(t1)))
{
return *static_cast<T1 &&>(t1);
}
template(typename T, typename T1)(
requires derived_from<detail::decay_t<T1>, T>)
static constexpr T1 && coerce(T1 && t1, int) noexcept
{
return static_cast<T1 &&>(t1);
}
template(typename, typename T1)(
requires detail::is_reference_wrapper_v<detail::decay_t<T1>>)
static constexpr decltype(auto) coerce(T1 && t1, int) noexcept
{
return static_cast<T1 &&>(t1).get();
}
public:
template<typename F, typename T, typename T1, typename... Args>
constexpr auto operator()(F T::*f, T1&& t1, Args&&... args) const
noexcept(noexcept((invoke_fn::coerce<T>((T1&&) t1, 0).*f)((Args&&) args...)))
-> decltype((invoke_fn::coerce<T>((T1&&) t1, 0).*f)((Args&&) args...))
{
return (invoke_fn::coerce<T>((T1&&) t1, 0).*f)((Args&&) args...);
}
template<typename D, typename T, typename T1>
constexpr auto operator()(D T::*f, T1&& t1) const
noexcept(noexcept(invoke_fn::coerce<T>((T1&&) t1, 0).*f))
-> decltype(invoke_fn::coerce<T>((T1&&) t1, 0).*f)
{
return invoke_fn::coerce<T>((T1&&) t1, 0).*f;
}
template<typename F, typename... Args>
CPP_PP_IIF(RANGES_CONSTEXPR_INVOKE)(CPP_PP_EXPAND, CPP_PP_EAT)(constexpr)
auto operator()(F&& f, Args&&... args) const
noexcept(noexcept(((F&&) f)((Args&&) args...)))
-> decltype(((F&&) f)((Args&&) args...))
{
return ((F&&) f)((Args&&) args...);
}
};
RANGES_INLINE_VARIABLE(invoke_fn, invoke)
#ifdef RANGES_WORKAROUND_MSVC_701385
/// \cond
namespace detail
{
template<typename Void, typename Fun, typename... Args>
struct _invoke_result_
{};
template<typename Fun, typename... Args>
struct _invoke_result_<
meta::void_<decltype(invoke(std::declval<Fun>(), std::declval<Args>()...))>,
Fun, Args...>
{
using type = decltype(invoke(std::declval<Fun>(), std::declval<Args>()...));
};
} // namespace detail
/// \endcond
template<typename Fun, typename... Args>
using invoke_result = detail::_invoke_result_<void, Fun, Args...>;
template<typename Fun, typename... Args>
using invoke_result_t = meta::_t<invoke_result<Fun, Args...>>;
#else // RANGES_WORKAROUND_MSVC_701385
template<typename Fun, typename... Args>
using invoke_result_t =
decltype(invoke(std::declval<Fun>(), std::declval<Args>()...));
template<typename Fun, typename... Args>
struct invoke_result : meta::defer<invoke_result_t, Fun, Args...>
{};
#endif // RANGES_WORKAROUND_MSVC_701385
/// \cond
namespace detail
{
template<bool IsInvocable>
struct is_nothrow_invocable_impl_
{
template<typename Fn, typename... Args>
static constexpr bool apply() noexcept
{
return false;
}
};
template<>
struct is_nothrow_invocable_impl_<true>
{
template<typename Fn, typename... Args>
static constexpr bool apply() noexcept
{
return noexcept(invoke(std::declval<Fn>(), std::declval<Args>()...));
}
};
} // namespace detail
/// \endcond
template<typename Fn, typename... Args>
RANGES_INLINE_VAR constexpr bool is_invocable_v =
meta::is_trait<invoke_result<Fn, Args...>>::value;
template<typename Fn, typename... Args>
RANGES_INLINE_VAR constexpr bool is_nothrow_invocable_v =
detail::is_nothrow_invocable_impl_<is_invocable_v<Fn, Args...>>::template apply<
Fn, Args...>();
/// \cond
template<typename Sig>
struct RANGES_DEPRECATED(
"ranges::result_of is deprecated. "
"Please use ranges::invoke_result") result_of
{};
template<typename Fun, typename... Args>
struct RANGES_DEPRECATED(
"ranges::result_of is deprecated. "
"Please use ranges::invoke_result") result_of<Fun(Args...)>
: meta::defer<invoke_result_t, Fun, Args...>
{};
/// \endcond
namespace cpp20
{
using ranges::invoke;
using ranges::invoke_result;
using ranges::invoke_result_t;
using ranges::is_invocable_v;
using ranges::is_nothrow_invocable_v;
} // namespace cpp20
/// @}
} // namespace ranges
RANGES_DIAGNOSTIC_POP
#include <range/v3/detail/epilogue.hpp>
#endif // RANGES_V3_FUNCTIONAL_INVOKE_HPP

View File

@@ -0,0 +1,98 @@
/// \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_FUNCTIONAL_NOT_FN_HPP
#define RANGES_V3_FUNCTIONAL_NOT_FN_HPP
#include <type_traits>
#include <concepts/concepts.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/concepts.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
template<typename FD>
struct logical_negate
{
private:
CPP_assert(same_as<FD, detail::decay_t<FD>> && move_constructible<FD>);
RANGES_NO_UNIQUE_ADDRESS FD pred_;
public:
CPP_member
constexpr CPP_ctor(logical_negate)()( //
noexcept(std::is_nothrow_default_constructible<FD>::value) //
requires default_constructible<FD>)
{}
template(typename T)(
requires (!same_as<detail::decay_t<T>, logical_negate>) AND
constructible_from<FD, T>)
constexpr explicit logical_negate(T && pred)
: pred_(static_cast<T &&>(pred))
{}
template(typename... Args)(
requires predicate<FD &, Args...>)
constexpr bool operator()(Args &&... args) &
{
return !invoke(pred_, static_cast<Args &&>(args)...);
}
/// \overload
template(typename... Args)(
requires predicate<FD const &, Args...>)
constexpr bool operator()(Args &&... args) const &
{
return !invoke(pred_, static_cast<Args &&>(args)...);
}
/// \overload
template(typename... Args)(
requires predicate<FD, Args...>)
constexpr bool operator()(Args &&... args) &&
{
return !invoke(static_cast<FD &&>(pred_), static_cast<Args &&>(args)...);
}
};
struct not_fn_fn
{
template(typename Pred)(
requires move_constructible<detail::decay_t<Pred>> AND
constructible_from<detail::decay_t<Pred>, Pred>)
constexpr logical_negate<detail::decay_t<Pred>> operator()(Pred && pred) const
{
return logical_negate<detail::decay_t<Pred>>{(Pred &&) pred};
}
};
/// \ingroup group-functional
/// \sa `not_fn_fn`
RANGES_INLINE_VARIABLE(not_fn_fn, not_fn)
namespace cpp20
{
using ranges::not_fn;
}
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,74 @@
/// \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_FUNCTIONAL_ON_HPP
#define RANGES_V3_FUNCTIONAL_ON_HPP
#include <concepts/concepts.hpp>
#include <range/v3/detail/config.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
template<typename Fn1, typename Fn2>
struct transformed
{
private:
RANGES_NO_UNIQUE_ADDRESS
Fn1 first_;
RANGES_NO_UNIQUE_ADDRESS
Fn2 second_;
public:
transformed() = default;
constexpr transformed(Fn1 fn1, Fn2 fn2)
: first_(static_cast<Fn1 &&>(fn1))
, second_(static_cast<Fn2 &&>(fn2))
{}
// clang-format off
template<typename... Args>
auto CPP_auto_fun(operator())(Args &&... args)
(
return invoke(first_, invoke(second_, static_cast<Args &&>(args)...))
)
template<typename... Args>
auto CPP_auto_fun(operator())(Args &&... args)(const)
(
return invoke((Fn1 const &)first_,
invoke((Fn2 const &)second_, static_cast<Args &&>(args))...)
)
// clang-format on
};
struct on_fn
{
template<typename Fn1, typename Fn2>
constexpr transformed<Fn1, Fn2> operator()(Fn1 fn1, Fn2 fn2) const
{
return transformed<Fn1, Fn2>{detail::move(fn1), detail::move(fn2)};
}
};
/// \ingroup group-functional
/// \sa `on_fn`
RANGES_INLINE_VARIABLE(on_fn, on)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,175 @@
/// \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_FUNCTIONAL_OVERLOAD_HPP
#define RANGES_V3_FUNCTIONAL_OVERLOAD_HPP
#include <meta/meta.hpp>
#include <concepts/concepts.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/concepts.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
/// \cond
namespace detail
{
struct _id
{
template<typename T>
using invoke = T;
};
struct _ref
{
template<typename T>
using invoke = T &;
};
struct _cref
{
template<typename T>
using invoke = T const &;
};
template<typename T>
struct _bind_front
{
template<typename... Args>
using invoke = invoke_result_t<T, Args...>;
};
} // namespace detail
/// \endcond
template<typename... Ts>
struct overloaded;
template<>
struct overloaded<>
{
private:
template<typename...>
friend struct overloaded;
template<typename, typename...>
using _result_t = void;
};
template<typename First, typename... Rest>
struct overloaded<First, Rest...>
{
private:
template<typename...>
friend struct overloaded;
RANGES_NO_UNIQUE_ADDRESS
First first_;
RANGES_NO_UNIQUE_ADDRESS
overloaded<Rest...> second_;
template<typename Qual>
using _result_first = detail::_bind_front<meta::invoke<Qual, First>>;
template<typename Qual>
struct _result_second
{
template<typename... Args>
using invoke = typename overloaded<Rest...>
::template _result_t<Qual, Args...>;
};
template<typename Qual, typename... Args>
using _result_t =
meta::invoke<
meta::conditional_t<
(bool) invocable<meta::invoke<Qual, First>, Args...>,
_result_first<Qual>,
_result_second<Qual>>,
Args...>;
public:
overloaded() = default;
constexpr overloaded(First first, Rest... rest)
: first_(static_cast<First &&>(first))
, second_{static_cast<Rest &&>(rest)...}
{}
template(typename... Args)(
requires invocable<First, Args...>)
constexpr _result_t<detail::_id, Args...> operator()(Args &&... args) &&
{
return invoke((First &&) first_, (Args &&) args...);
}
template(typename... Args)(
requires (!invocable<First, Args...>) AND
invocable<overloaded<Rest...>, Args...>)
constexpr _result_t<detail::_id, Args...> operator()(Args &&... args) &&
{
return invoke((overloaded<Rest...> &&) second_, (Args &&) args...);
}
template(typename... Args)(
requires invocable<First &, Args...>)
constexpr _result_t<detail::_ref, Args...> operator()(Args &&... args) &
{
return invoke(first_, (Args &&) args...);
}
template(typename... Args)(
requires (!invocable<First &, Args...>) AND
invocable<overloaded<Rest...> &, Args...>)
constexpr _result_t<detail::_ref, Args...> operator()(Args &&... args) &
{
return invoke(second_, (Args &&) args...);
}
template(typename... Args)(
requires invocable<First const &, Args...>)
constexpr _result_t<detail::_cref, Args...> operator()(Args &&... args) const &
{
return invoke(first_, (Args &&) args...);
}
template(typename... Args)(
requires (!invocable<First const &, Args...>) AND
invocable<overloaded<Rest...> const &, Args...>)
constexpr _result_t<detail::_cref, Args...> operator()(Args &&... args) const &
{
return invoke(second_, (Args &&) args...);
}
};
struct overload_fn
{
template<typename Fn>
constexpr Fn operator()(Fn fn) const
{
return fn;
}
template<typename... Fns>
constexpr overloaded<Fns...> operator()(Fns... fns) const
{
return overloaded<Fns...>{static_cast<Fns &&>(fns)...};
}
};
/// \ingroup group-functional
/// \sa `overload_fn`
RANGES_INLINE_VARIABLE(overload_fn, overload)
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,128 @@
/// \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_FUNCTIONAL_PIPEABLE_HPP
#define RANGES_V3_FUNCTIONAL_PIPEABLE_HPP
#include <concepts/concepts.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/functional/compose.hpp>
#include <range/v3/functional/concepts.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
struct pipeable_base;
template<typename T>
RANGES_INLINE_VAR constexpr bool is_pipeable_v = META_IS_BASE_OF(pipeable_base, T);
template<typename T>
RANGES_INLINE_VAR constexpr bool is_pipeable_v<T &> = META_IS_BASE_OF(pipeable_base,
T);
template<typename T>
RANGES_INLINE_VAR constexpr bool is_pipeable_v<T &&> = META_IS_BASE_OF(pipeable_base,
T);
template<typename T>
using is_pipeable = meta::bool_<is_pipeable_v<T>>;
struct make_pipeable_fn
{
template<typename Fun, typename PipeableBase = pipeable_base>
constexpr auto operator()(Fun fun) const
{
struct local
: Fun
, PipeableBase
{
constexpr explicit local(Fun && f)
: Fun(static_cast<Fun &&>(f))
{}
};
return local{static_cast<Fun &&>(fun)};
}
};
/// \ingroup group-functional
/// \sa `make_pipeable_fn`
RANGES_INLINE_VARIABLE(make_pipeable_fn, make_pipeable)
struct pipeable_access
{
template<typename Pipeable>
struct impl : Pipeable
{
using Pipeable::pipe;
};
};
struct pipeable_base
{
private:
friend pipeable_access;
// Evaluate the pipe with an argument
template(typename Arg, typename Pipe)(
requires (!is_pipeable_v<Arg>) AND is_pipeable_v<Pipe> AND
invocable<Pipe, Arg>) // clang-format off
friend constexpr auto operator|(Arg &&arg, Pipe pipe) // clang-format off
{
return static_cast<Pipe &&>(pipe)(static_cast<Arg &&>(arg));
}
// Compose two pipes
template(typename Pipe0, typename Pipe1)(
requires is_pipeable_v<Pipe0> AND is_pipeable_v<Pipe1>) // clang-format off
friend constexpr auto operator|(Pipe0 pipe0, Pipe1 pipe1) // clang-format on
{
return make_pipeable(compose(detail::move(pipe1), detail::move(pipe0)));
}
template<typename Arg, typename Pipe>
friend auto operator|=(Arg & arg, Pipe pipe) //
-> CPP_broken_friend_ret(Arg &)(
requires (is_pipeable_v<Pipe>) &&
(!is_pipeable_v<Arg>) && invocable<Pipe, Arg &>)
{
static_cast<Pipe &&>(pipe)(arg);
return arg;
}
// Default Pipe behavior just passes the argument to the pipe's function call
// operator
// clang-format off
template<typename Arg, typename Pipe>
static constexpr auto CPP_auto_fun(pipe)(Arg && arg, Pipe p)
(
return static_cast<Pipe &&>(p)(static_cast<Arg &&>(arg))
)
// clang-format on
};
template<typename>
using pipeable RANGES_DEPRECATED("Please use pipeable_base instead") = pipeable_base;
/// \endcond
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif

View File

@@ -0,0 +1,184 @@
/// \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_FUNCTIONAL_REFERENCE_WRAPPER_HPP
#define RANGES_V3_FUNCTIONAL_REFERENCE_WRAPPER_HPP
#include <type_traits>
#include <utility>
#include <meta/meta.hpp>
#include <concepts/concepts.hpp>
#include <range/v3/functional/invoke.hpp>
#include <range/v3/utility/addressof.hpp>
#include <range/v3/utility/static_const.hpp>
#include <range/v3/detail/prologue.hpp>
namespace ranges
{
/// \addtogroup group-functional
/// @{
/// \cond
namespace detail
{
template<typename T>
struct reference_wrapper_
{
T * t_ = nullptr;
constexpr reference_wrapper_() = default;
constexpr reference_wrapper_(T & t) noexcept
: t_(detail::addressof(t))
{}
constexpr reference_wrapper_(T &&) = delete;
constexpr T & get() const noexcept
{
return *t_;
}
};
template<typename T>
struct reference_wrapper_<T &> : reference_wrapper_<T>
{
using reference_wrapper_<T>::reference_wrapper_;
};
template<typename T>
struct reference_wrapper_<T &&>
{
T * t_ = nullptr;
constexpr reference_wrapper_() = default;
constexpr reference_wrapper_(T && t) noexcept
: t_(detail::addressof(t))
{}
constexpr T && get() const noexcept
{
return static_cast<T &&>(*t_);
}
};
} // namespace detail
/// \endcond
// Can be used to store rvalue references in addition to lvalue references.
// Also, see: https://wg21.link/lwg2993
template<typename T>
struct reference_wrapper : private detail::reference_wrapper_<T>
{
private:
using base_ = detail::reference_wrapper_<T>;
using base_::t_;
public:
using type = meta::_t<std::remove_reference<T>>;
using reference = meta::if_<std::is_reference<T>, T, T &>;
constexpr reference_wrapper() = default;
template(typename U)(
requires (!same_as<uncvref_t<U>, reference_wrapper>) AND
constructible_from<base_, U>)
constexpr reference_wrapper(U && u) noexcept(
std::is_nothrow_constructible<base_, U>::value)
: detail::reference_wrapper_<T>{static_cast<U &&>(u)}
{}
constexpr reference get() const noexcept
{
return this->base_::get();
}
constexpr operator reference() const noexcept
{
return get();
}
template(typename...)(
requires (!std::is_rvalue_reference<T>::value)) //
constexpr operator std::reference_wrapper<type>() const noexcept
{
return {get()};
}
// clang-format off
template<typename ...Args>
constexpr auto CPP_auto_fun(operator())(Args &&...args) (const)
(
return invoke(static_cast<reference>(*t_), static_cast<Args &&>(args)...)
)
// clang-format on
};
struct ref_fn
{
template(typename T)(
requires (!is_reference_wrapper_v<T>)) //
constexpr reference_wrapper<T> operator()(T & t) const
{
return {t};
}
/// \overload
template<typename T>
constexpr reference_wrapper<T> operator()(reference_wrapper<T> t) const
{
return t;
}
/// \overload
template<typename T>
constexpr reference_wrapper<T> operator()(std::reference_wrapper<T> t) const
{
return {t.get()};
}
};
/// \ingroup group-functional
/// \sa `ref_fn`
RANGES_INLINE_VARIABLE(ref_fn, ref)
template<typename T>
using ref_t = decltype(ref(std::declval<T>()));
struct unwrap_reference_fn
{
template<typename T>
constexpr T && operator()(T && t) const noexcept
{
return static_cast<T &&>(t);
}
/// \overload
template<typename T>
constexpr typename reference_wrapper<T>::reference operator()(reference_wrapper<T> t) const
noexcept
{
return t.get();
}
/// \overload
template<typename T>
constexpr T & operator()(std::reference_wrapper<T> t) const noexcept
{
return t.get();
}
/// \overload
template<typename T>
constexpr T & operator()(ref_view<T> t) const noexcept
{
return t.base();
}
};
/// \ingroup group-functional
/// \sa `unwrap_reference_fn`
RANGES_INLINE_VARIABLE(unwrap_reference_fn, unwrap_reference)
template<typename T>
using unwrap_reference_t = decltype(unwrap_reference(std::declval<T>()));
/// @}
} // namespace ranges
#include <range/v3/detail/epilogue.hpp>
#endif