add types::upper_bound_index meta-function

This commit is contained in:
bolero-MURAKAMI 2013-07-11 03:05:49 +09:00
parent 9d7d243886
commit a7def70996
3 changed files with 96 additions and 14 deletions

View file

@ -5,5 +5,6 @@
#include <sprout/type/algorithm/find_index.hpp>
#include <sprout/type/algorithm/find_index_if.hpp>
#include <sprout/type/algorithm/lower_bound_index.hpp>
#include <sprout/type/algorithm/upper_bound_index.hpp>
#endif // #ifndef SPROUT_TYPE_ALGORITHM_HPP

View file

@ -10,30 +10,50 @@
namespace sprout {
namespace types {
namespace detail {
template<std::size_t I, typename Tuple, typename T, typename Compare, typename = void>
struct lower_bound_index_impl
: public std::integral_constant<std::size_t, I>
{};
template<std::size_t I, typename Tuple, typename T, typename Compare>
struct lower_bound_index_impl<
I, Tuple, T, Compare,
typename std::enable_if<(I < sprout::tuples::tuple_size<Tuple>::value)>::type
template<
typename Tuple, typename T, typename Compare, std::size_t First, std::size_t Last,
std::size_t Distance = (Last - First)
>
struct lower_bound_index_impl;
template<
typename Tuple, typename T, typename Compare, std::size_t First, std::size_t Last
>
struct lower_bound_index_impl<
Tuple, T, Compare, First, Last,
0
>
: public std::integral_constant<std::size_t, Last>
{};
template<
typename Tuple, typename T, typename Compare, std::size_t First, std::size_t Last
>
struct lower_bound_index_impl<
Tuple, T, Compare, First, Last,
1
>
: public std::integral_constant<
std::size_t,
Compare::template apply<typename sprout::types::tuple_element<First, Tuple>::type, T>::type::value ? Last : First
>
{};
template<
typename Tuple, typename T, typename Compare, std::size_t First, std::size_t Last,
std::size_t Distance
>
struct lower_bound_index_impl
: public std::conditional<
Compare::template apply<typename sprout::tuples::tuple_element<I, Tuple>::type, T>::type::value,
sprout::types::detail::lower_bound_index_impl<I + 1, Tuple, T, Compare>,
std::integral_constant<std::size_t, I>
Compare::template apply<typename sprout::types::tuple_element<First + Distance / 2, Tuple>::type, T>::type::value,
sprout::types::detail::lower_bound_index_impl<Tuple, T, Compare, First + Distance / 2, Last>,
sprout::types::detail::lower_bound_index_impl<Tuple, T, Compare, First, First + Distance / 2>
>::type
{};
} // namespace detail
//
// lower_bound_index
//
// TODO: O(log N) implementation
//
template<typename Tuple, typename T, typename Compare = sprout::types::less_>
struct lower_bound_index
: public sprout::types::detail::lower_bound_index_impl<0, Tuple, T, Compare>
: public sprout::types::detail::lower_bound_index_impl<Tuple, T, Compare, 0, sprout::types::tuple_size<Tuple>::value>
{};
} // namespace types
} // namespace sprout

View file

@ -0,0 +1,61 @@
#ifndef SPROUT_TYPE_ALGORITHM_UPPER_BOUND_INDEX_HPP
#define SPROUT_TYPE_ALGORITHM_UPPER_BOUND_INDEX_HPP
#include <cstddef>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/type/functional/less.hpp>
#include <sprout/type/tuple.hpp>
namespace sprout {
namespace types {
namespace detail {
template<
typename Tuple, typename T, typename Compare, std::size_t First, std::size_t Last,
std::size_t Distance = (Last - First)
>
struct upper_bound_index_impl;
template<
typename Tuple, typename T, typename Compare, std::size_t First, std::size_t Last
>
struct upper_bound_index_impl<
Tuple, T, Compare, First, Last,
0
>
: public std::integral_constant<std::size_t, Last>
{};
template<
typename Tuple, typename T, typename Compare, std::size_t First, std::size_t Last
>
struct upper_bound_index_impl<
Tuple, T, Compare, First, Last,
1
>
: public std::integral_constant<
std::size_t,
!Compare::template apply<T, typename sprout::types::tuple_element<First, Tuple>::type>::type::value ? Last : First
>
{};
template<
typename Tuple, typename T, typename Compare, std::size_t First, std::size_t Last,
std::size_t Distance
>
struct upper_bound_index_impl
: public std::conditional<
!Compare::template apply<T, typename sprout::types::tuple_element<First + Distance / 2, Tuple>::type>::type::value,
sprout::types::detail::upper_bound_index_impl<Tuple, T, Compare, First + Distance / 2, Last>,
sprout::types::detail::upper_bound_index_impl<Tuple, T, Compare, First, First + Distance / 2>
>::type
{};
} // namespace detail
//
// upper_bound_index
//
template<typename Tuple, typename T, typename Compare = sprout::types::less_>
struct upper_bound_index
: public sprout::types::detail::upper_bound_index_impl<Tuple, T, Compare, 0, sprout::types::tuple_size<Tuple>::value>
{};
} // namespace types
} // namespace sprout
#endif // #ifndef SPROUT_TYPE_ALGORITHM_UPPER_BOUND_INDEX_HPP