108 lines
3.3 KiB
C++
108 lines
3.3 KiB
C++
// Copyright (C) 2022 T. Zachary Laine
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See
|
|
// accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
#ifndef BOOST_STL_INTERFACES_DETAIL_VIEW_CLOSURE_HPP
|
|
#define BOOST_STL_INTERFACES_DETAIL_VIEW_CLOSURE_HPP
|
|
|
|
#include <boost/stl_interfaces/detail/pipeable_view.hpp>
|
|
|
|
#include <utility>
|
|
|
|
|
|
namespace boost { namespace stl_interfaces { namespace detail {
|
|
|
|
template<std::size_t I, typename T>
|
|
struct box
|
|
{
|
|
T value_;
|
|
};
|
|
|
|
template<typename Indices, typename Func, typename... T>
|
|
struct view_closure_impl;
|
|
|
|
template<std::size_t... I, typename Func, typename... T>
|
|
struct view_closure_impl<std::index_sequence<I...>, Func, T...>
|
|
: box<I, T>...
|
|
{
|
|
view_closure_impl() = default;
|
|
constexpr explicit view_closure_impl(Func, T &&... x) :
|
|
box<I, T>{std::move(x)}...
|
|
{}
|
|
|
|
#if BOOST_STL_INTERFACES_USE_CONCEPTS
|
|
template<std::ranges::input_range R>
|
|
requires std::ranges::viewable_range<R> &&
|
|
std::invocable<Func, R, T &...> &&
|
|
std::ranges::view<std::invoke_result_t<Func, R, T &...>>
|
|
constexpr auto operator()(R && r) &
|
|
#else
|
|
template<typename R>
|
|
constexpr auto operator()(R && r) & -> decltype(
|
|
Func{}((R &&) r, std::declval<box<I, T> &>().value_...))
|
|
#endif
|
|
{
|
|
return Func{}((R &&) r, static_cast<box<I, T> &>(*this).value_...);
|
|
}
|
|
|
|
#if BOOST_STL_INTERFACES_USE_CONCEPTS
|
|
template<std::ranges::input_range R>
|
|
requires std::ranges::viewable_range<R> &&
|
|
std::invocable<Func, R, T const &...> &&
|
|
std::ranges::view<std::invoke_result_t<Func, R, T const &...>>
|
|
constexpr auto operator()(R && r) const &
|
|
#else
|
|
template<typename R>
|
|
constexpr auto operator()(R && r) const & -> decltype(
|
|
Func{}((R &&) r, std::declval<box<I, T> const &>().value_...))
|
|
#endif
|
|
{
|
|
return Func{}(
|
|
(R &&) r, static_cast<box<I, T> const &>(*this).value_...);
|
|
}
|
|
|
|
#if BOOST_STL_INTERFACES_USE_CONCEPTS
|
|
template<std::ranges::input_range R>
|
|
requires std::ranges::viewable_range<R> &&
|
|
std::invocable<Func, R, T...> &&
|
|
std::ranges::view<std::invoke_result_t<Func, R, T...>>
|
|
constexpr auto operator()(R && r) &&
|
|
#else
|
|
template<typename R>
|
|
constexpr auto operator()(R && r) && -> decltype(
|
|
Func{}((R &&) r, std::declval<box<I, T> &&>().value_...))
|
|
#endif
|
|
{
|
|
return Func{}((R &&) r, static_cast<box<I, T> &&>(*this).value_...);
|
|
}
|
|
};
|
|
|
|
#if BOOST_STL_INTERFACES_USE_CONCEPTS
|
|
template<std::semiregular Func, std::copy_constructible... T>
|
|
#else
|
|
template<typename Func, typename... T>
|
|
#endif
|
|
struct view_closure
|
|
: pipeable<view_closure<Func, T...>>,
|
|
view_closure_impl<std::index_sequence_for<T...>, Func, T...>
|
|
{
|
|
using base_type =
|
|
view_closure_impl<std::index_sequence_for<T...>, Func, T...>;
|
|
|
|
view_closure() = default;
|
|
|
|
constexpr explicit view_closure(Func func, T &&... x) :
|
|
base_type{func, std::move(x)...}
|
|
{}
|
|
};
|
|
|
|
#if defined(__cpp_deduction_guides)
|
|
template<typename Func, typename... T>
|
|
view_closure(Func, T...) -> view_closure<Func, T...>;
|
|
#endif
|
|
|
|
}}}
|
|
|
|
#endif
|