Skip to content

Commit

Permalink
refs #121 Слияние разных диапазонов
Browse files Browse the repository at this point in the history
  • Loading branch information
izvolov committed Jul 19, 2020
1 parent 41349d0 commit 3b5b163
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 6 deletions.
63 changes: 63 additions & 0 deletions include/burst/iterator/detail/uniform_range_tuple_please.hpp
@@ -0,0 +1,63 @@
#ifndef BURST_ITERATOR_DETAIL_MERGE_ITERATOR_HPP
#define BURST_ITERATOR_DETAIL_MERGE_ITERATOR_HPP

#include <burst/range/to_any_range.hpp>
#include <burst/tuple/by_all.hpp>
#include <burst/type_traits/are_same.hpp>

#include <boost/iterator/iterator_categories.hpp>

#include <tuple>
#include <type_traits>

namespace burst
{
namespace detail
{
/*!
\brief
Перегрузка для случая, когда все переданные диапазоны имеют один и тот же тип
\see merge_iterator
*/
template <typename... Ranges>
auto uniform_range_tuple_please_impl (std::tuple<Ranges &...> ranges, std::true_type)
{
static_assert(are_same_v<Ranges...>, "");
return ranges;
}

/*!
\brief
Перегрузка для случая, когда переданные диапазоны разнотипны
\see merge_iterator
*/
template <typename... Ranges>
auto uniform_range_tuple_please_impl (std::tuple<Ranges &...> ranges, std::false_type)
{
static_assert(not are_same_v<Ranges...>, "");
return by_all(to_any_range<boost::forward_traversal_tag>, ranges);
}

/*!
\brief
Сделать из кортежа возможно разнотипных диапазонов кортеж заведомо однотипных
диапазонов
\returns
Если диапазоны изначально однотипны, то возвращается изначальный кортеж, в
противном случае создаётся кортеж, в котором каждый из диапазонов приведён к
boost::any_range.
\see merge_iterator
*/
template <typename... Ranges>
auto uniform_range_tuple_please (std::tuple<Ranges &...> ranges)
{
return uniform_range_tuple_please_impl(ranges, are_same<Ranges...>{});
}
}
}

#endif // BURST_ITERATOR_DETAIL_MERGE_ITERATOR_HPP
12 changes: 6 additions & 6 deletions include/burst/iterator/merge_iterator.hpp
Expand Up @@ -4,6 +4,7 @@
#include <burst/container/access/front.hpp>
#include <burst/functional/each.hpp>
#include <burst/functional/invert.hpp>
#include <burst/iterator/detail/uniform_range_tuple_please.hpp>
#include <burst/iterator/end_tag.hpp>
#include <burst/range/make_range_vector.hpp>
#include <burst/range/own_as_range.hpp>
Expand All @@ -21,6 +22,7 @@
#include <algorithm>
#include <functional>
#include <iterator>
#include <tuple>
#include <utility>

namespace burst
Expand Down Expand Up @@ -206,10 +208,11 @@ namespace burst
template <typename ... Ranges, typename Compare>
auto make_merge_iterator (std::tuple<Ranges &...> ranges, Compare compare)
{
auto common_ranges = detail::uniform_range_tuple_please(ranges);
return
make_merge_iterator
(
burst::own_as_range(burst::apply(burst::make_range_vector, ranges)),
burst::own_as_range(burst::apply(burst::make_range_vector, common_ranges)),
std::move(compare)
);
}
Expand Down Expand Up @@ -252,11 +255,8 @@ namespace burst
template <typename ... Ranges>
auto make_merge_iterator (std::tuple<Ranges &...> ranges)
{
return
make_merge_iterator
(
burst::own_as_range(burst::apply(burst::make_range_vector, ranges))
);
auto common_ranges = detail::uniform_range_tuple_please(ranges);
return make_merge_iterator(own_as_range(burst::apply(make_range_vector, common_ranges)));
}

//! Функция для создания итератора на конец слияния с предикатом.
Expand Down
27 changes: 27 additions & 0 deletions include/burst/range/to_any_range.hpp
@@ -0,0 +1,27 @@
#ifndef BURST_RANGE_TO_ANY_RANGE_HPP
#define BURST_RANGE_TO_ANY_RANGE_HPP

#include <burst/type_traits/range_reference.hpp>
#include <burst/type_traits/range_value.hpp>

#include <boost/range/any_range.hpp>

namespace burst
{
template <typename Traversal>
struct to_any_range_t
{
template <typename Range>
constexpr auto operator () (Range && range) const
{
using value_type = range_value_t<Range>;
using reference_type = range_reference_t<Range>;
return boost::any_range<value_type, Traversal, reference_type>(range);
}
};

template <typename Traversal>
constexpr auto to_any_range = to_any_range_t<Traversal>{};
} // namespace burst

#endif // BURST_RANGE_TO_ANY_RANGE_HPP
17 changes: 17 additions & 0 deletions include/burst/type_traits/are_same.hpp
@@ -0,0 +1,17 @@
#ifndef BURST_TYPE_TRAITS_ARE_SAME_HPP
#define BURST_TYPE_TRAITS_ARE_SAME_HPP

#include <burst/type_traits/type_list.hpp>

#include <type_traits>

namespace burst
{
template <typename T, typename... Ts>
struct are_same: std::is_same<type_list<T, Ts...>, type_list<Ts..., T>> {};

template <typename... Ts>
constexpr const auto are_same_v = are_same<Ts...>::value;
} // namespace burst

#endif // BURST_TYPE_TRAITS_ARE_SAME_HPP
10 changes: 10 additions & 0 deletions include/burst/type_traits/type_list.hpp
@@ -0,0 +1,10 @@
#ifndef BURST_TYPE_TRAITS_TYPE_LIST_HPP
#define BURST_TYPE_TRAITS_TYPE_LIST_HPP

namespace burst
{
template <typename... Ts>
struct type_list {};
} // namespace burst

#endif // BURST_TYPE_TRAITS_TYPE_LIST_HPP
25 changes: 25 additions & 0 deletions test/burst/range/merge.cpp
@@ -1,3 +1,4 @@
#include <burst/container/make_deque.hpp>
#include <burst/container/make_list.hpp>
#include <burst/container/make_vector.hpp>
#include <burst/range/make_range_vector.hpp>
Expand Down Expand Up @@ -83,4 +84,28 @@ TEST_SUITE("merge")
auto expected_collection = {0, 1, 2, 3, 4, 5, 6, 7, 8};
CHECK(merged_range == expected_collection);
}

TEST_CASE("Можно сливать диапазоны разных типов")
{
auto one = burst::make_vector({0, 3, 6, 9});
auto two = burst::make_list({1, 4, 7, 10});
auto three = burst::make_deque({2, 5, 8, 11});

auto merged_range = burst::merge(std::tie(one, two, three));

auto expected_collection = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
CHECK(merged_range == expected_collection);
}

TEST_CASE("Можно сливать с предикатом диапазоны разных типов")
{
auto one = burst::make_vector({9, 6, 3, 0});
auto two = burst::make_list({10, 7, 4, 1});
auto three = burst::make_deque({11, 8, 5, 2});

auto merged_range = burst::merge(std::tie(one, two, three), std::greater<>{});

auto expected_collection = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
CHECK(merged_range == expected_collection);
}
}

0 comments on commit 3b5b163

Please sign in to comment.