boost/stl_interfaces/detail/view_closure.hpp
// 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