eedb/share/include/range/v3/range_access.hpp
Wieczorek Bartosz f4ef592706 add ranges lib
2017-03-18 08:15:40 +01:00

445 lines
15 KiB
C++

/// \file
// Range v3 library
//
// Copyright Eric Niebler 2014
// 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_RANGE_ACCESS_HPP
#define RANGES_V3_RANGE_ACCESS_HPP
#include <cstddef>
#include <utility>
#include <meta/meta.hpp>
#include <range/v3/range_fwd.hpp>
#include <range/v3/utility/concepts.hpp>
namespace ranges
{
inline namespace v3
{
/// \addtogroup group-core
/// @{
struct range_access
{
/// \cond
private:
template<typename T>
static std::false_type single_pass_2_(long);
template<typename T>
static typename T::single_pass single_pass_2_(int);
template<typename T>
struct single_pass_
{
using type = decltype(range_access::single_pass_2_<T>(42));
};
template<typename T>
static meta::id<basic_mixin<T>> mixin_base_2_(long);
template<typename T>
static meta::id<typename T::mixin> mixin_base_2_(int);
template<typename Cur>
struct mixin_base_
: decltype(range_access::mixin_base_2_<Cur>(42))
{};
public:
template<typename Cur>
using single_pass_t = meta::_t<single_pass_<Cur>>;
template<typename Cur>
using mixin_base_t = meta::_t<mixin_base_<Cur>>;
//
// Concepts that the range cursor must model
//
struct Cursor
{
template<typename T>
auto requires_() -> decltype(
concepts::valid_expr(
concepts::model_of<concepts::SemiRegular, T>(),
concepts::model_of<concepts::SemiRegular, mixin_base_t<T>>(),
concepts::model_of<concepts::Constructible, mixin_base_t<T>, T>(),
concepts::model_of<concepts::Constructible, mixin_base_t<T>, T const &>()
));
};
struct HasCursorNext
{
template<typename T>
auto requires_(T &t) -> decltype(
concepts::valid_expr(
(t.next(), concepts::void_)
));
};
struct CursorSentinel
: concepts::refines<concepts::SemiRegular(concepts::_1), Cursor(concepts::_2)>
{
template<typename S, typename C>
auto requires_(S &s, C &c) -> decltype(
concepts::valid_expr(
concepts::convertible_to<bool>(c.equal(s))
));
};
struct ReadableCursor
{
template<typename T>
auto requires_(T &t) -> decltype(
concepts::valid_expr(
t.read()
));
};
struct HasCursorArrow
{
template<typename C>
auto requires_(C const &c) -> decltype(
concepts::valid_expr(
c.arrow()
));
};
struct WritableCursor
{
template<typename T, typename U>
auto requires_(T &t, U &&u) -> decltype(
concepts::valid_expr(
(t.write((U &&) u), 42)
));
};
struct SizedCursorSentinel
: concepts::refines<CursorSentinel>
{
template<typename S, typename C>
auto requires_(S &s, C &c) -> decltype(
concepts::valid_expr(
concepts::model_of<concepts::SignedIntegral>(c.distance_to(s))
));
};
struct OutputCursor
: concepts::refines<WritableCursor, Cursor(concepts::_1)>
{};
struct InputCursor
: concepts::refines<ReadableCursor, Cursor, HasCursorNext>
{};
struct ForwardCursor
: concepts::refines<InputCursor, CursorSentinel(concepts::_1, concepts::_1)>
{
template<typename T>
auto requires_() -> decltype(
concepts::valid_expr(
concepts::is_false(single_pass_t<uncvref_t<T>>())
));
};
struct BidirectionalCursor
: concepts::refines<ForwardCursor>
{
template<typename T>
auto requires_(T &t) -> decltype(
concepts::valid_expr(
(t.prev(), concepts::void_)
));
};
struct RandomAccessCursor
: concepts::refines<BidirectionalCursor, SizedCursorSentinel(concepts::_1, concepts::_1)>
{
template<typename T>
auto requires_(T &t) -> decltype(
concepts::valid_expr(
(t.advance(t.distance_to(t)), concepts::void_)
));
};
struct InfiniteCursor
{
template<typename T>
auto requires_() -> decltype(
concepts::valid_expr(
concepts::is_true(typename T::is_infinite{})
));
};
template<typename Rng>
static RANGES_CXX14_CONSTEXPR auto begin_cursor(Rng & rng, long)
RANGES_DECLTYPE_AUTO_RETURN
(
rng.begin_cursor()
)
template<typename Rng>
static RANGES_CXX14_CONSTEXPR auto begin_cursor(Rng & rng, int)
RANGES_DECLTYPE_AUTO_RETURN
(
static_cast<Rng const &>(rng).begin_cursor()
)
template<typename Rng>
static RANGES_CXX14_CONSTEXPR auto end_cursor(Rng & rng, long)
RANGES_DECLTYPE_AUTO_RETURN
(
rng.end_cursor()
)
template<typename Rng>
static RANGES_CXX14_CONSTEXPR auto end_cursor(Rng & rng, int)
RANGES_DECLTYPE_AUTO_RETURN
(
static_cast<Rng const &>(rng).end_cursor()
)
template<typename Rng>
static RANGES_CXX14_CONSTEXPR auto begin_adaptor(Rng & rng, long)
RANGES_DECLTYPE_AUTO_RETURN
(
rng.begin_adaptor()
)
template<typename Rng>
static RANGES_CXX14_CONSTEXPR auto begin_adaptor(Rng & rng, int)
RANGES_DECLTYPE_AUTO_RETURN
(
static_cast<Rng const &>(rng).begin_adaptor()
)
template<typename Rng>
static RANGES_CXX14_CONSTEXPR auto end_adaptor(Rng & rng, long)
RANGES_DECLTYPE_AUTO_RETURN
(
rng.end_adaptor()
)
template<typename Rng>
static RANGES_CXX14_CONSTEXPR auto end_adaptor(Rng & rng, int)
RANGES_DECLTYPE_AUTO_RETURN
(
static_cast<Rng const &>(rng).end_adaptor()
)
template<typename Cur>
static RANGES_CXX14_CONSTEXPR auto read(Cur const &pos)
RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
(
pos.read()
)
template<typename Cur>
static RANGES_CXX14_CONSTEXPR auto arrow(Cur const &pos)
RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
(
pos.arrow()
)
template<typename Cur>
static RANGES_CXX14_CONSTEXPR auto move(Cur const &pos)
RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
(
pos.move()
)
template<typename Cur, typename T>
static RANGES_CXX14_CONSTEXPR auto write(Cur &pos, T && t)
RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
(
pos.write((T &&) t)
)
template<typename Cur>
static RANGES_CXX14_CONSTEXPR auto next(Cur & pos)
RANGES_DECLTYPE_AUTO_RETURN
(
pos.next()
)
template<typename Cur, typename O>
static RANGES_CXX14_CONSTEXPR auto equal(Cur const &pos, O const &other)
RANGES_DECLTYPE_AUTO_RETURN
(
pos.equal(other)
)
template<typename Cur>
static RANGES_CXX14_CONSTEXPR auto prev(Cur & pos)
RANGES_DECLTYPE_AUTO_RETURN
(
pos.prev()
)
template<typename Cur, typename D>
static RANGES_CXX14_CONSTEXPR auto advance(Cur & pos, D n)
RANGES_DECLTYPE_AUTO_RETURN
(
pos.advance(n)
)
template<typename Cur, typename O>
static RANGES_CXX14_CONSTEXPR auto distance_to(Cur const &pos, O const &other)
RANGES_DECLTYPE_AUTO_RETURN
(
pos.distance_to(other)
)
private:
template<typename Cur>
using sized_cursor_difference_t =
decltype(range_access::distance_to(std::declval<Cur>(), std::declval<Cur>()));
template<typename T>
static std::ptrdiff_t cursor_difference_2_(detail::any);
template<typename T>
static sized_cursor_difference_t<T> cursor_difference_2_(long);
template<typename T>
static typename T::difference_type cursor_difference_2_(int);
template<typename Cur>
struct cursor_difference
{
using type = decltype(range_access::cursor_difference_2_<Cur>(42));
};
template<typename T>
using cursor_reference_t = decltype(std::declval<T const &>().read());
template<typename T>
static meta::id<uncvref_t<cursor_reference_t<T>>> cursor_value_2_(long);
template<typename T>
static meta::id<typename T::value_type> cursor_value_2_(int);
template<typename Cur>
struct cursor_value
: decltype(range_access::cursor_value_2_<Cur>(42))
{};
public:
template<typename Cur>
using cursor_difference_t = typename cursor_difference<Cur>::type;
template<typename Cur>
using cursor_value_t = typename cursor_value<Cur>::type;
template<typename Cur>
static RANGES_CXX14_CONSTEXPR Cur &pos(basic_iterator<Cur> &it) noexcept
{
return it.pos();
}
template<typename Cur>
static constexpr Cur const &pos(basic_iterator<Cur> const &it) noexcept
{
return it.pos();
}
template<typename Cur>
static RANGES_CXX14_CONSTEXPR Cur &&pos(basic_iterator<Cur> &&it) noexcept
{
return detail::move(it.pos());
}
template<typename Cur>
static RANGES_CXX14_CONSTEXPR Cur cursor(basic_iterator<Cur> it)
{
return std::move(it.pos());
}
private:
template<typename RangeAdaptor>
static meta::id<typename RangeAdaptor::base_range_t> base_range_2_();
template<typename RangeFacade>
static meta::id<typename RangeFacade::view_facade_t> view_facade_2_();
public:
template<typename RangeAdaptor>
struct base_range
: decltype(range_access::base_range_2_<RangeAdaptor>())
{};
template<typename RangeAdaptor>
struct base_range<RangeAdaptor const>
: std::add_const<meta::_t<base_range<RangeAdaptor>>>
{};
template<typename RangeFacade>
struct view_facade
: decltype(range_access::view_facade_2_<RangeFacade>())
{};
/// endcond
};
/// @}
/// \cond
namespace detail
{
template<typename T>
using Cursor =
concepts::models<range_access::Cursor, T>;
template<typename S, typename C>
using CursorSentinel =
concepts::models<range_access::CursorSentinel, S, C>;
template<typename T>
using ReadableCursor =
concepts::models<range_access::ReadableCursor, T>;
template<typename T, typename U>
using WritableCursor =
concepts::models<range_access::WritableCursor, T, U>;
template<typename T>
using HasCursorNext =
concepts::models<range_access::HasCursorNext, T>;
template<typename T>
using HasCursorArrow =
concepts::models<range_access::HasCursorArrow, T>;
template<typename S, typename C>
using SizedCursorSentinel =
concepts::models<range_access::SizedCursorSentinel, S, C>;
template<typename T, typename U>
using OutputCursor =
concepts::models<range_access::OutputCursor, T, U>;
template<typename T>
using InputCursor =
concepts::models<range_access::InputCursor, T>;
template<typename T>
using ForwardCursor =
concepts::models<range_access::ForwardCursor, T>;
template<typename T>
using BidirectionalCursor =
concepts::models<range_access::BidirectionalCursor, T>;
template<typename T>
using RandomAccessCursor =
concepts::models<range_access::RandomAccessCursor, T>;
template<typename T>
using InfiniteCursor =
concepts::models<range_access::InfiniteCursor, T>;
template<typename T>
using cursor_concept =
concepts::most_refined<
meta::list<
range_access::RandomAccessCursor,
range_access::BidirectionalCursor,
range_access::ForwardCursor,
range_access::InputCursor,
range_access::Cursor>, T>;
template<typename T>
using cursor_concept_t = meta::_t<cursor_concept<T>>;
template<typename Cur, bool Readable = (bool) ReadableCursor<Cur>()>
struct is_writable_cursor_
: std::true_type
{};
template<typename Cur>
struct is_writable_cursor_<Cur, true>
: WritableCursor<Cur, range_access::cursor_value_t<Cur>>
{};
template<typename Cur>
struct is_writable_cursor
: detail::is_writable_cursor_<Cur>
{};
}
/// \endcond
}
}
#endif