ecency-mobile/ios/Pods/boost-for-react-native/boost/hana/range.hpp

295 lines
10 KiB
C++

/*!
@file
Defines `boost::hana::range`.
@copyright Louis Dionne 2013-2016
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_HANA_RANGE_HPP
#define BOOST_HANA_RANGE_HPP
#include <boost/hana/fwd/range.hpp>
#include <boost/hana/bool.hpp>
#include <boost/hana/concept/integral_constant.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/common.hpp>
#include <boost/hana/core/to.hpp>
#include <boost/hana/core/tag_of.hpp>
#include <boost/hana/detail/operators/adl.hpp>
#include <boost/hana/detail/operators/comparable.hpp>
#include <boost/hana/detail/operators/iterable.hpp>
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/back.hpp>
#include <boost/hana/fwd/contains.hpp>
#include <boost/hana/fwd/drop_front.hpp>
#include <boost/hana/fwd/drop_front_exactly.hpp>
#include <boost/hana/fwd/equal.hpp>
#include <boost/hana/fwd/find.hpp>
#include <boost/hana/fwd/front.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/length.hpp>
#include <boost/hana/fwd/maximum.hpp>
#include <boost/hana/fwd/minimum.hpp>
#include <boost/hana/fwd/product.hpp>
#include <boost/hana/fwd/sum.hpp>
#include <boost/hana/fwd/unpack.hpp>
#include <boost/hana/integral_constant.hpp> // required by fwd decl and below
#include <boost/hana/optional.hpp>
#include <boost/hana/value.hpp>
#include <cstddef>
#include <utility>
BOOST_HANA_NAMESPACE_BEGIN
//////////////////////////////////////////////////////////////////////////
// range<>
//////////////////////////////////////////////////////////////////////////
//! @cond
template <typename T, T From, T To>
struct range
: detail::operators::adl<range<T, From, To>>
, detail::iterable_operators<range<T, From, To>>
{
static_assert(From <= To,
"hana::make_range(from, to) requires 'from <= to'");
using value_type = T;
static constexpr value_type from = From;
static constexpr value_type to = To;
};
//! @endcond
template <typename T, T From, T To>
struct tag_of<range<T, From, To>> {
using type = range_tag;
};
//////////////////////////////////////////////////////////////////////////
// make<range_tag>
//////////////////////////////////////////////////////////////////////////
template <>
struct make_impl<range_tag> {
template <typename From, typename To>
static constexpr auto apply(From const&, To const&) {
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
static_assert(hana::IntegralConstant<From>::value,
"hana::make_range(from, to) requires 'from' to be an IntegralConstant");
static_assert(hana::IntegralConstant<To>::value,
"hana::make_range(from, to) requires 'to' to be an IntegralConstant");
#endif
using T = typename common<
typename hana::tag_of<From>::type::value_type,
typename hana::tag_of<To>::type::value_type
>::type;
constexpr T from = hana::to<T>(From::value);
constexpr T to = hana::to<T>(To::value);
return range<T, from, to>{};
}
};
//////////////////////////////////////////////////////////////////////////
// Operators
//////////////////////////////////////////////////////////////////////////
namespace detail {
template <>
struct comparable_operators<range_tag> {
static constexpr bool value = true;
};
}
//////////////////////////////////////////////////////////////////////////
// Comparable
//////////////////////////////////////////////////////////////////////////
template <>
struct equal_impl<range_tag, range_tag> {
template <typename R1, typename R2>
static constexpr auto apply(R1 const&, R2 const&) {
return hana::bool_c<
(R1::from == R1::to && R2::from == R2::to) ||
(R1::from == R2::from && R1::to == R2::to)
>;
}
};
//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
template <>
struct unpack_impl<range_tag> {
template <typename T, T from, typename F, T ...v>
static constexpr decltype(auto)
unpack_helper(F&& f, std::integer_sequence<T, v...>) {
return static_cast<F&&>(f)(integral_constant<T, from + v>{}...);
}
template <typename T, T from, T to, typename F>
static constexpr decltype(auto) apply(range<T, from, to> const&, F&& f) {
return unpack_helper<T, from>(static_cast<F&&>(f),
std::make_integer_sequence<T, to - from>{});
}
};
template <>
struct length_impl<range_tag> {
template <typename T, T from, T to>
static constexpr auto apply(range<T, from, to> const&)
{ return hana::size_c<static_cast<std::size_t>(to - from)>; }
};
template <>
struct minimum_impl<range_tag> {
template <typename T, T from, T to>
static constexpr auto apply(range<T, from, to> const&)
{ return integral_c<T, from>; }
};
template <>
struct maximum_impl<range_tag> {
template <typename T, T from, T to>
static constexpr auto apply(range<T, from, to> const&)
{ return integral_c<T, to-1>; }
};
template <>
struct sum_impl<range_tag> {
// Returns the sum of `[m, n]`, where `m <= n` always hold.
template <typename I>
static constexpr I sum_helper(I m, I n) {
if (m == n)
return m;
// 0 == m < n
else if (0 == m)
return n * (n+1) / 2;
// 0 < m < n
else if (0 < m)
return sum_helper(0, n) - sum_helper(0, m-1);
// m < 0 <= n
else if (0 <= n)
return sum_helper(0, n) - sum_helper(0, -m);
// m < n < 0
else
return -sum_helper(-n, -m);
}
template <typename, typename T, T from, T to>
static constexpr auto apply(range<T, from, to> const&) {
return integral_c<T, from == to ? 0 : sum_helper(from, to-1)>;
}
};
template <>
struct product_impl<range_tag> {
// Returns the product of `[m, n)`, where `m <= n` always hold.
template <typename I>
static constexpr I product_helper(I m, I n) {
if (m <= 0 && 0 < n)
return 0;
else {
I p = 1;
for (; m != n; ++m)
p *= m;
return p;
}
}
template <typename, typename T, T from, T to>
static constexpr auto apply(range<T, from, to> const&)
{ return integral_c<T, product_helper(from, to)>; }
};
//////////////////////////////////////////////////////////////////////////
// Searchable
//////////////////////////////////////////////////////////////////////////
template <>
struct find_impl<range_tag> {
template <typename T, T from, typename N>
static constexpr auto find_helper(hana::true_) {
constexpr T n = N::value;
return hana::just(hana::integral_c<T, n>);
}
template <typename T, T from, typename N>
static constexpr auto find_helper(hana::false_)
{ return hana::nothing; }
template <typename T, T from, T to, typename N>
static constexpr auto apply(range<T, from, to> const&, N const&) {
constexpr auto n = N::value;
return find_helper<T, from, N>(hana::bool_c<(n >= from && n < to)>);
}
};
template <>
struct contains_impl<range_tag> {
template <typename T, T from, T to, typename N>
static constexpr auto apply(range<T, from, to> const&, N const&) {
constexpr auto n = N::value;
return bool_c<(n >= from && n < to)>;
}
};
//////////////////////////////////////////////////////////////////////////
// Iterable
//////////////////////////////////////////////////////////////////////////
template <>
struct front_impl<range_tag> {
template <typename T, T from, T to>
static constexpr auto apply(range<T, from, to> const&)
{ return integral_c<T, from>; }
};
template <>
struct is_empty_impl<range_tag> {
template <typename T, T from, T to>
static constexpr auto apply(range<T, from, to> const&)
{ return bool_c<from == to>; }
};
template <>
struct at_impl<range_tag> {
template <typename T, T from, T to, typename N>
static constexpr auto apply(range<T, from, to> const&, N const&) {
constexpr auto n = N::value;
return integral_c<T, from + n>;
}
};
template <>
struct back_impl<range_tag> {
template <typename T, T from, T to>
static constexpr auto apply(range<T, from, to> const&)
{ return integral_c<T, to - 1>; }
};
template <>
struct drop_front_impl<range_tag> {
template <typename T, T from, T to, typename N>
static constexpr auto apply(range<T, from, to> const&, N const&) {
constexpr auto n = N::value;
return range<T, (to < from + n ? to : from + n), to>{};
}
};
template <>
struct drop_front_exactly_impl<range_tag> {
template <typename T, T from, T to, typename N>
static constexpr auto apply(range<T, from, to> const&, N const&) {
constexpr auto n = N::value;
return range<T, from + n, to>{};
}
};
BOOST_HANA_NAMESPACE_END
#endif // !BOOST_HANA_RANGE_HPP