mirror of
https://github.com/boostorg/stl_interfaces.git
synced 2026-01-19 04:42:12 +00:00
Break take_view out into its own header, in example/.
This commit is contained in:
141
example/take_view.hpp
Normal file
141
example/take_view.hpp
Normal file
@@ -0,0 +1,141 @@
|
||||
// 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_EXAMPLE_TAKE_VIEW_HPP
|
||||
#define BOOST_STL_INTERFACES_EXAMPLE_TAKE_VIEW_HPP
|
||||
#include "all_view.hpp"
|
||||
|
||||
namespace detail {
|
||||
//[ take_view_defn
|
||||
// This is a really simple iterator that converts the given iterator Iter
|
||||
// to a forward_iterator that counts how many times it has ben
|
||||
// incremented. It counts down from an initial count to zero.
|
||||
template<typename Iter>
|
||||
struct take_iterator
|
||||
: boost::stl_interfaces::iterator_interface<
|
||||
take_iterator<Iter>,
|
||||
std::forward_iterator_tag,
|
||||
typename std::iterator_traits<Iter>::value_type,
|
||||
typename std::iterator_traits<Iter>::reference,
|
||||
typename std::iterator_traits<Iter>::pointer,
|
||||
typename std::iterator_traits<Iter>::difference_type>
|
||||
{
|
||||
constexpr take_iterator() = default;
|
||||
constexpr explicit take_iterator(Iter it, int n) :
|
||||
it_(std::move(it)), n_(n)
|
||||
{}
|
||||
|
||||
constexpr Iter base() const { return it_; }
|
||||
constexpr int count() const { return n_; }
|
||||
|
||||
constexpr take_iterator & operator++()
|
||||
{
|
||||
++it_;
|
||||
--n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
friend boost::stl_interfaces::access;
|
||||
constexpr Iter & base_reference() { return it_; }
|
||||
constexpr Iter const & base_reference() const { return it_; }
|
||||
|
||||
template<typename Iter2>
|
||||
friend struct take_iterator;
|
||||
|
||||
Iter it_;
|
||||
int n_;
|
||||
};
|
||||
|
||||
// This sentinel compares equal to any take_iterator whose count has
|
||||
// reached zero.
|
||||
template<typename Sentinel>
|
||||
struct take_sentinel
|
||||
{
|
||||
take_sentinel() = default;
|
||||
explicit take_sentinel(Sentinel sent) : sent_(sent) {}
|
||||
|
||||
template<typename Iter>
|
||||
friend constexpr bool
|
||||
operator==(take_iterator<Iter> it, take_sentinel s)
|
||||
{
|
||||
return !it.count() || it.base() == s.sent_;
|
||||
}
|
||||
template<typename Iter>
|
||||
friend constexpr bool
|
||||
operator!=(take_iterator<Iter> it, take_sentinel s)
|
||||
{
|
||||
return !(it == s);
|
||||
}
|
||||
|
||||
private:
|
||||
Sentinel sent_;
|
||||
};
|
||||
|
||||
// The take_iterator and take_sentinel templates do all the hard work,
|
||||
// which keeps take_view quie simple.
|
||||
#if BOOST_STL_INTERFACES_USE_CONCEPTS
|
||||
template<std::ranges::view View>
|
||||
requires std::is_object_v<View>
|
||||
#else
|
||||
template<
|
||||
typename View,
|
||||
typename Enable = std::enable_if_t<std::is_object<View>::value>>
|
||||
#endif
|
||||
struct take_view : boost::stl_interfaces::view_interface<take_view<View>>
|
||||
{
|
||||
using iterator = take_iterator<iterator_t<View>>;
|
||||
using sentinel = take_sentinel<sentinel_t<View>>;
|
||||
|
||||
// We don't need a phony initial int param for this constructor, since
|
||||
// it already takes two parameters; it won't get confused for a copy
|
||||
// or a move. The count here is just an int to keep things simple.
|
||||
#if BOOST_STL_INTERFACES_USE_CONCEPTS
|
||||
template<typename View2>
|
||||
requires std::is_same_v<std::remove_reference_t<View2>, View>
|
||||
#else
|
||||
template<
|
||||
typename View2,
|
||||
typename E = std::enable_if_t<
|
||||
std::is_same<std::remove_reference_t<View2>, View>::value>>
|
||||
#endif
|
||||
explicit take_view(View2 && r, int n) :
|
||||
first_(r.begin(), n), last_(r.end())
|
||||
{}
|
||||
|
||||
iterator begin() const { return first_; }
|
||||
sentinel end() const { return last_; }
|
||||
|
||||
private:
|
||||
iterator first_;
|
||||
sentinel last_;
|
||||
};
|
||||
|
||||
// This just makes out implementations below a bit easier to write.
|
||||
#if defined(__cpp_deduction_guides)
|
||||
template<typename R>
|
||||
take_view(R &&, int)->detail::take_view<std::remove_reference_t<R>>;
|
||||
#endif
|
||||
//]
|
||||
}
|
||||
|
||||
#if defined(__cpp_deduction_guides)
|
||||
//[ take_defn
|
||||
|
||||
// Use the adaptor template to support calling the given lambda with either
|
||||
// all the parameters or all the parameters after the first.
|
||||
inline constexpr boost::stl_interfaces::adaptor take =
|
||||
[]<typename R>(R && r, int n) { return detail::take_view((R &&) r, n); };
|
||||
//]
|
||||
#endif
|
||||
|
||||
#if BOOST_STL_INTERFACES_USE_CONCEPTS
|
||||
namespace std::ranges {
|
||||
template<typename View>
|
||||
inline constexpr bool enable_borrowed_range<detail::take_view<View>> = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "ill_formed.hpp"
|
||||
#include "../example/all_view.hpp"
|
||||
#include "../example/reverse_view.hpp"
|
||||
#include "../example/take_view.hpp"
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
|
||||
@@ -17,178 +18,61 @@
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace detail {
|
||||
#if BOOST_STL_INTERFACES_USE_CONCEPTS
|
||||
template<std::ranges::view View>
|
||||
requires std::is_object_v<View>
|
||||
#else
|
||||
template<
|
||||
typename View,
|
||||
typename Enable = std::enable_if_t<std::is_object<View>::value>>
|
||||
#endif
|
||||
struct take_view
|
||||
: boost::stl_interfaces::view_interface<take_view<View>>
|
||||
namespace detail {
|
||||
template<
|
||||
typename R,
|
||||
bool ReverseView = is_reverse_view<std::decay_t<R>>::value>
|
||||
struct reverse_impl_impl
|
||||
{
|
||||
static constexpr auto call(R && r) { return ((R &&) r).base(); }
|
||||
};
|
||||
template<typename R>
|
||||
struct reverse_impl_impl<R, false>
|
||||
{
|
||||
static constexpr auto call(R && r)
|
||||
{
|
||||
template<typename Iter>
|
||||
struct counted_iterator
|
||||
: boost::stl_interfaces::iterator_interface<
|
||||
counted_iterator<Iter>,
|
||||
std::forward_iterator_tag,
|
||||
typename std::iterator_traits<Iter>::value_type,
|
||||
typename std::iterator_traits<Iter>::reference,
|
||||
typename std::iterator_traits<Iter>::pointer,
|
||||
typename std::iterator_traits<Iter>::difference_type>
|
||||
{
|
||||
constexpr counted_iterator() = default;
|
||||
constexpr explicit counted_iterator(Iter it, int n) :
|
||||
it_(std::move(it)), n_(n)
|
||||
{}
|
||||
return reverse_view<std::remove_reference_t<R>>(0, (R &&) r);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr Iter base() const { return it_; }
|
||||
constexpr int count() const { return n_; }
|
||||
|
||||
constexpr counted_iterator & operator++()
|
||||
{
|
||||
++it_;
|
||||
--n_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
friend boost::stl_interfaces::access;
|
||||
constexpr Iter & base_reference() { return it_; }
|
||||
constexpr Iter const & base_reference() const { return it_; }
|
||||
|
||||
template<typename Iter2>
|
||||
friend struct counted_iterator;
|
||||
|
||||
Iter it_;
|
||||
int n_;
|
||||
};
|
||||
|
||||
template<typename Sentinel>
|
||||
struct counted_sentinel
|
||||
{
|
||||
counted_sentinel() = default;
|
||||
explicit counted_sentinel(Sentinel sent) : sent_(sent) {}
|
||||
|
||||
template<typename Iter>
|
||||
friend constexpr bool
|
||||
operator==(counted_iterator<Iter> it, counted_sentinel s)
|
||||
{
|
||||
return !it.count() || it.base() == s.sent_;
|
||||
}
|
||||
template<typename Iter>
|
||||
friend constexpr bool
|
||||
operator!=(counted_iterator<Iter> it, counted_sentinel s)
|
||||
{
|
||||
return !(it == s);
|
||||
}
|
||||
|
||||
private:
|
||||
Sentinel sent_;
|
||||
};
|
||||
|
||||
using iterator = counted_iterator<iterator_t<View>>;
|
||||
using sentinel = counted_sentinel<sentinel_t<View>>;
|
||||
|
||||
#if BOOST_STL_INTERFACES_USE_CONCEPTS
|
||||
template<typename View2>
|
||||
requires std::is_same_v<std::remove_reference_t<View2>, View>
|
||||
#else
|
||||
template<
|
||||
typename View2,
|
||||
typename E = std::enable_if_t<
|
||||
std::is_same<std::remove_reference_t<View2>, View>::value>>
|
||||
#endif
|
||||
explicit take_view(View2 && r, int n) :
|
||||
first_(r.begin(), n), last_(r.end())
|
||||
{}
|
||||
|
||||
iterator begin() const { return first_; }
|
||||
sentinel end() const { return last_; }
|
||||
|
||||
private:
|
||||
iterator first_;
|
||||
sentinel last_;
|
||||
};
|
||||
|
||||
struct take_impl
|
||||
{
|
||||
template<typename R>
|
||||
constexpr auto operator()(R && r, int n) const
|
||||
{
|
||||
return take_view<std::remove_reference_t<R>>((R &&) r, n);
|
||||
}
|
||||
|
||||
constexpr auto operator()(int n) const
|
||||
{
|
||||
using closure_func_type =
|
||||
decltype(boost::stl_interfaces::bind_back(*this, n));
|
||||
return boost::stl_interfaces::closure<closure_func_type>(
|
||||
boost::stl_interfaces::bind_back(*this, n));
|
||||
}
|
||||
};
|
||||
|
||||
template<
|
||||
typename R,
|
||||
bool ReverseView = is_reverse_view<std::decay_t<R>>::value>
|
||||
struct reverse_impl_impl
|
||||
{
|
||||
static constexpr auto call(R && r) { return ((R &&) r).base(); }
|
||||
};
|
||||
struct reverse_impl
|
||||
: boost::stl_interfaces::range_adaptor_closure<reverse_impl>
|
||||
{
|
||||
template<typename R>
|
||||
struct reverse_impl_impl<R, false>
|
||||
constexpr auto operator()(R && r) const
|
||||
{
|
||||
static constexpr auto call(R && r)
|
||||
{
|
||||
return reverse_view<std::remove_reference_t<R>>(0, (R &&) r);
|
||||
}
|
||||
};
|
||||
return reverse_impl_impl<R>::call((R &&) r);
|
||||
}
|
||||
};
|
||||
|
||||
struct reverse_impl
|
||||
: boost::stl_interfaces::range_adaptor_closure<reverse_impl>
|
||||
struct take_impl
|
||||
{
|
||||
template<typename R>
|
||||
constexpr auto operator()(R && r, int n) const
|
||||
{
|
||||
template<typename R>
|
||||
constexpr auto operator()(R && r) const
|
||||
{
|
||||
return reverse_impl_impl<R>::call((R &&) r);
|
||||
}
|
||||
};
|
||||
}
|
||||
return take_view<std::remove_reference_t<R>>((R &&) r, n);
|
||||
}
|
||||
|
||||
#if BOOST_STL_INTERFACES_USE_CONCEPTS
|
||||
|
||||
namespace std::ranges {
|
||||
template<typename View>
|
||||
inline constexpr bool enable_borrowed_range<detail::take_view<View>> = true;
|
||||
constexpr auto operator()(int n) const
|
||||
{
|
||||
using closure_func_type =
|
||||
decltype(boost::stl_interfaces::bind_back(*this, n));
|
||||
return boost::stl_interfaces::closure<closure_func_type>(
|
||||
boost::stl_interfaces::bind_back(*this, n));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cpp_inline_variables)
|
||||
inline constexpr detail::reverse_impl old_reverse;
|
||||
#else
|
||||
namespace {
|
||||
constexpr detail::reverse_impl old_reverse;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__cpp_inline_variables)
|
||||
inline constexpr detail::take_impl old_take;
|
||||
#else
|
||||
namespace {
|
||||
constexpr detail::reverse_impl old_reverse;
|
||||
constexpr detail::take_impl old_take;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 201703L <= __cplusplus
|
||||
inline constexpr boost::stl_interfaces::adaptor take =
|
||||
[]<typename R>(R && r, int n) {
|
||||
return detail::take_view<std::remove_reference_t<R>>((R &&) r, n);
|
||||
};
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
// non-closures
|
||||
|
||||
Reference in New Issue
Block a user