/* * Range-adapted standard algorithms for C++14 * * Copyright snsinfu 2016-2018. * Distributed under the Boost Software License, Version 1.0. * * Permission is hereby granted, free of charge, to any person or organization * obtaining a copy of the software and accompanying documentation covered by * this license (the "Software") to use, reproduce, display, distribute, * execute, and transmit the Software, and to prepare derivative works of the * Software, and to permit third-parties to whom the Software is furnished to * do so, all subject to the following: * * The copyright notices in the Software and this entire statement, including * the above license grant, this restriction and the following disclaimer, * must be included in all copies of the Software, in whole or in part, and * all derivative works of the Software, unless such copies or derivative * works are solely in the form of machine-executable object code generated by * a source language processor. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef INCLUDED_RANGE_HPP #define INCLUDED_RANGE_HPP #include #include #include #include #include namespace range { using std::begin; using std::end; template using iterator_t = std::decay_t()))>; template using sentinel_t = std::decay_t()))>; template using traits = std::iterator_traits>; template using value_t = typename traits::value_type; template using reference_t = typename traits::reference; template using pointer_t = typename traits::pointer; template using difference_t = typename traits::difference_type; /* * Iterator range. The interface mimics that of std::string_view. */ template struct range { using iterator = Iterator; using sentinel = Sentinel; using traits = std::iterator_traits; using value_type = typename traits::value_type; using reference = typename traits::reference; using difference_type = typename traits::difference_type; using iterator_category = typename traits::iterator_category; /* * Creates an iterator range [first,last). */ range(iterator first, sentinel last) : first_{first} , last_{last} { } /* * O(1). */ iterator begin() const { return first_; } /* * O(1). */ sentinel end() const { return last_; } /* * O(1). */ bool empty() const { return begin() == end(); } /* * O(1) for RandomAccessIterator, or O(N) otherwise. Invalidates * InputIterator. */ difference_type size() const { return std::distance(begin(), end()); } /* * O(1) for RandomAccessIterator, or O(n) otherwise. Invalidates * InputIterator. */ range prefix(difference_type n) const { return {begin(), std::next(begin(), n)}; } /* * O(1) for RandomAccessIterator, O(n) for BidirectionalIterator. */ range suffix(difference_type n) const { return {std::prev(end(), n), end()}; } /* * O(1) for RandomAccessIterator, or O(offset) otherwise. Invalidates * InputIterator. */ range subrange(difference_type offset) const { return {std::next(begin(), offset), end()}; } /* * O(1) for RandomAccessIterator, or O(offset+count) otherwise. * Invalidates InputIterator. */ range subrange(difference_type offset, difference_type count) const { return subrange(offset).prefix(count); } /* * O(1) for RandomAccessIterator, or O(n) otherwise. */ range& remove_prefix(difference_type n) { std::advance(first_, n); return *this; } /* * O(1) for RandomAccessIterator, O(n) for BidirectionalIterator. */ range& remove_suffix(difference_type n) { std::advance(last_, -n); return *this; } /* * O(1). */ reference front() const { return *begin(); } /* * O(1). Provided only for BidirectionalIterator or stronger iterators. */ reference back() const { return *std::prev(end()); } /* * O(1). Provided only for RandomAccessIterator. */ reference operator[](difference_type idx) const { return *(begin() + idx); } private: iterator first_; sentinel last_; }; /* * Creates an iterator range [first,last). */ template range make(Iterator first, Sentinel last) { return {first, last}; } template range, sentinel_t> make(Range&& r) { return {begin(r), end(r)}; } // All of template bool all_of(InputRange&& r, Predicate pred) { return std::all_of(begin(r), end(r), pred); } // Any of template bool any_of(InputRange&& r, Predicate pred) { return std::any_of(begin(r), end(r), pred); } // None of template bool none_of(InputRange&& r, Predicate pred) { return std::none_of(begin(r), end(r), pred); } // For each template Function for_each(InputRange&& r, Function f) { return std::for_each(begin(r), end(r), f); } // Find template iterator_t find(InputRange&& r, T const& value) { return std::find(begin(r), end(r), value); } template iterator_t find_if(InputRange&& r, Predicate pred) { return std::find_if(begin(r), end(r), pred); } template iterator_t find_if_not(InputRange&& r, Predicate pred) { return std::find_if_not(begin(r), end(r), pred); } // Find end template iterator_t find_end(ForwardRange1&& r1, ForwardRange2&& r2) { return std::find_end(begin(r1), end(r1), begin(r2), end(r2)); } template iterator_t find_end(ForwardRange1&& r1, ForwardRange2&& r2, BinaryPredicate pred) { return std::find_end(begin(r1), end(r1), begin(r2), end(r2), pred); } // Find first template iterator_t find_first_of(InputRange&& r1, ForwardRange&& r2) { return std::find_first_of(begin(r1), end(r1), begin(r2), end(r2)); } template iterator_t find_first_of(InputRange&& r1, ForwardRange&& r2, BinaryPredicate pred) { return std::find_first_of(begin(r1), end(r1), begin(r2), end(r2), pred); } // Adjacent find template iterator_t adjacent_find(ForwardRange&& r) { return std::adjacent_find(begin(r), end(r)); } template iterator_t adjacent_find(ForwardRange&& r, BinaryPredicate pred) { return std::adjacent_find(begin(r), end(r), pred); } // Count template difference_t count(InputRange&& r, T const& value) { return std::count(begin(r), end(r), value); } template difference_t count_if(InputRange&& r, Predicate pred) { return std::count_if(begin(r), end(r), pred); } // Mismatch template std::pair, iterator_t> mismatch(InputRange1&& r1, InputRange2&& r2) { return std::mismatch(begin(r1), end(r1), begin(r2), end(r2)); } template std::pair, iterator_t> mismatch(InputRange1&& r1, InputRange2&& r2, BinaryPredicate pred) { return std::mismatch(begin(r1), end(r1), begin(r2), end(r2), pred); } // Equal template bool equal(InputRange1&& r1, InputRange2&& r2) { return std::equal(begin(r1), end(r1), begin(r2), end(r2)); } template bool equal(InputRange1&& r1, InputRange2&& r2, BinaryPredicate pred) { return std::equal(begin(r1), end(r1), begin(r2), end(r2), pred); } // Is permutation template bool is_permutation(ForwardRange1&& r1, ForwardRange2&& r2) { return std::is_permutation(begin(r1), end(r1), begin(r2), end(r2)); } template bool is_permutation(ForwardRange1&& r1, ForwardRange2&& r2, BinaryPredicate pred) { return std::is_permutation(begin(r1), end(r1), begin(r2), end(r2), pred); } // Search template iterator_t search(ForwardRange1&& r1, ForwardRange2&& r2) { return std::search(begin(r1), end(r1), begin(r2), end(r2)); } template iterator_t search(ForwardRange1&& r1, ForwardRange2&& r2, BinaryPredicate pred) { return std::search(begin(r1), end(r1), begin(r2), end(r2), pred); } template iterator_t search_n(ForwardRange&& r, Size count, T const& value) { return std::search_n(begin(r), end(r), count, value); } template iterator_t search_n(ForwardRange&& r, Size count, T const& value, BinaryPredicate pred) { return std::search_n(begin(r), end(r), count, value, pred); } // Copy template OutputIterator copy(InputRange&& r, OutputIterator result) { return std::copy(begin(r), end(r), result); } template OutputIterator copy_n(InputRange&& r, Size n, OutputIterator result) { return std::copy_n(begin(r), n, result); } template OutputIterator copy_if(InputRange&& r, OutputIterator result, Predicate pred) { return std::copy_if(begin(r), end(r), result, pred); } template BidirectionalIterator copy_backward(BidirectionalRange&& r, BidirectionalIterator result) { return std::copy_backward(begin(r), end(r), result); } // Move template OutputIterator move(InputRange&& r, OutputIterator result) { return std::move(begin(r), end(r), result); } template BidirectionalIterator move_backward(BidirectionalRange&& r, BidirectionalIterator result) { return std::move_backward(begin(r), end(r), result); } // Swap template iterator_t swap_ranges(ForwardRange1&& r1, ForwardRange2&& r2) { return std::swap_ranges(begin(r1), end(r1), begin(r2)); } //template //void iter_swap(ForwardIterator1 a, ForwardIterator2 b); // Transform template OutputIterator transform(InputRange&& r, OutputIterator result, UnaryOperation op) { return std::transform(begin(r), end(r), result, op); } template OutputIterator transform(InputRange1&& r1, InputRange2&& r2, OutputIterator result, BinaryOperation op) { return std::transform(begin(r1), end(r1), begin(r2), result, op); } // Replace template void replace(ForwardRange&& r, T const& old_value, T const& new_value) { std::replace(begin(r), end(r), old_value, new_value); } template void replace_if(ForwardRange&& r, Predicate pred, T const& new_value) { std::replace_if(begin(r), end(r), pred, new_value); } template OutputIterator replace_copy(InputRange&& r, OutputIterator result, T const& old_value, T const& new_value) { return std::replace_copy(begin(r), end(r), result, old_value, new_value); } template OutputIterator replace_copy_if(InputRange&& r, OutputIterator result, Predicate pred, T const& new_value) { return std::replace_copy_if(begin(r), end(r), result, pred, new_value); } // Fill template void fill(ForwardRange&& r, T const& value) { std::fill(begin(r), end(r), value); } template OutputIterator fill_n(OutputIterator first, Size n, T const& value) { return std::fill_n(first, n, value); } // Generate template void generate(ForwardRange&& r, Generator gen) { std::generate(begin(r), end(r), gen); } template OutputIterator generate_n(OutputIterator first, Size n, Generator gen) { return std::generate_n(first, n, gen); } // Remove template iterator_t remove(ForwardRange&& r, T const& value) { return std::remove(begin(r), end(r), value); } template iterator_t remove_if(ForwardRange&& r, Predicate pred) { return std::remove_if(begin(r), end(r), pred); } template OutputIterator remove_copy(ForwardRange&& r, OutputIterator result, T const& value) { return std::remove_copy(begin(r), end(r), result, value); } template OutputIterator remove_copy_if(ForwardRange&& r, OutputIterator result, Predicate pred) { return std::remove_copy_if(begin(r), end(r), result, pred); } // Unique template iterator_t unique(ForwardRange&& r) { return std::unique(begin(r), end(r)); } template iterator_t unique(ForwardRange&& r, BinaryPredicate pred) { return std::unique(begin(r), end(r), pred); } template OutputIterator unique_copy(InputRange&& r, OutputIterator result) { return std::unique_copy(begin(r), end(r), result); } template OutputIterator unique_copy(InputRange&& r, OutputIterator result, BinaryPredicate pred) { return std::unique_copy(begin(r), end(r), result, pred); } // Reverse template void reverse(BidirectionalRange&& r) { std::reverse(begin(r), end(r)); } template OutputIterator reverse_copy(BidirectionalRange&& r, OutputIterator result) { return std::reverse_copy(begin(r), end(r), result); } // Rotate namespace detail { template ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last, std::false_type) { return std::rotate(first, middle, last); } template ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last, std::true_type) { std::rotate(first, middle, last); return std::next(first, std::distance(middle, last)); } } template iterator_t rotate(ForwardRange&& r, iterator_t middle) { using pre_cxx14 = std::is_same< decltype(std::rotate(begin(r), middle, end(r))), void >; return detail::rotate(begin(r), middle, end(r), pre_cxx14{}); } template OutputIterator rotate_copy(ForwardRange&& r, iterator_t middle, OutputIterator result) { return std::rotate_copy(begin(r), middle, end(r), result); } // Shuffle template void shuffle(RandomAccessRange&& r, URNG&& rand) { std::shuffle(begin(r), end(r), std::forward(rand)); } // Partitions template bool is_partitioned(InputRange&& r, Predicate pred) { return std::is_partitioned(begin(r), end(r), pred); } template iterator_t partition(ForwardRange&& r, Predicate pred) { return std::partition(begin(r), end(r), pred); } template iterator_t stable_partition(BidirectionalRange&& r, Predicate pred) { return std::stable_partition(begin(r), end(r), pred); } template std::pair partition_copy(InputRange&& r, OutputIterator1 out_true, OutputIterator2 out_false, Predicate pred) { return std::partition_copy(begin(r), end(r), out_true, out_false, pred); } template iterator_t partition_point(ForwardRange&& r, Predicate pred) { return std::partition_point(begin(r), end(r), pred); } // Sorting template void sort(RandomAccessRange&& r) { std::sort(begin(r), end(r)); } template void sort(RandomAccessRange&& r, Compare comp) { std::sort(begin(r), end(r), comp); } template void stable_sort(RandomAccessRange&& r) { std::stable_sort(begin(r), end(r)); } template void stable_sort(RandomAccessRange&& r, Compare comp) { std::stable_sort(begin(r), end(r), comp); } template void partial_sort(RandomAccessRange&& r, iterator_t middle) { std::partial_sort(begin(r), middle, end(r)); } template void partial_sort(RandomAccessRange&& r, iterator_t middle, Compare comp) { std::partial_sort(begin(r), middle, end(r), comp); } template iterator_t partial_sort_copy(InputRange&& r, RandomAccessRange&& d) { return std::partial_sort_copy(begin(r), end(r), begin(d), end(d)); } template iterator_t partial_sort_copy(InputRange&& r, RandomAccessRange&& d, Compare comp) { return std::partial_sort_copy(begin(r), end(r), begin(d), end(d), comp); } template bool is_sorted(ForwardRange&& r) { return std::is_sorted(begin(r), end(r)); } template bool is_sorted(ForwardRange&& r, Compare comp) { return std::is_sorted(begin(r), end(r), comp); } template iterator_t is_sorted_until(ForwardRange&& r) { return std::is_sorted_until(begin(r), end(r)); } template iterator_t is_sorted_until(ForwardRange&& r, Compare comp) { return std::is_sorted_until(begin(r), end(r), comp); } // N-th element template void nth_element(RandomAccessRange&& r, iterator_t nth) { std::nth_element(begin(r), nth, end(r)); } template void nth_element(RandomAccessRange&& r, iterator_t nth, Compare comp) { std::nth_element(begin(r), nth, end(r), comp); } // Binary search template iterator_t lower_bound(ForwardRange&& r, T const& value) { return std::lower_bound(begin(r), end(r), value); } template iterator_t lower_bound(ForwardRange&& r, T const& value, Compare comp) { return std::lower_bound(begin(r), end(r), value, comp); } template iterator_t upper_bound(ForwardRange&& r, T const& value) { return std::upper_bound(begin(r), end(r), value); } template iterator_t upper_bound(ForwardRange&& r, T const& value, Compare comp) { return std::upper_bound(begin(r), end(r), value, comp); } template range> equal_range(ForwardRange&& r, T const& value) { auto pair = std::equal_range(begin(r), end(r), value); return {pair.first, pair.second}; } template range> equal_range(ForwardRange&& r, T const& value, Compare comp) { auto pair = std::equal_range(begin(r), end(r), value, comp); return {pair.first, pair.second}; } template bool binary_search(ForwardRange&& r, T const& value) { return std::binary_search(begin(r), end(r), value); } template bool binary_search(ForwardRange&& r, T const& value, Compare comp) { return std::binary_search(begin(r), end(r), value, comp); } // Merge template OutputIterator merge(InputRange1&& r1, InputRange2&& r2, OutputIterator result) { return std::merge(begin(r1), end(r1), begin(r2), end(r2), result); } template OutputIterator merge(InputRange1&& r1, InputRange2&& r2, OutputIterator result, Compare comp) { return std::merge(begin(r1), end(r1), begin(r2), end(r2), result, comp); } template void inplace_merge(BidirectionalRange&& r, iterator_t middle) { std::inplace_merge(begin(r), middle, end(r)); } template void inplace_merge(BidirectionalRange&& r, iterator_t middle, Compare comp) { std::inplace_merge(begin(r), middle, end(r), comp); } // Set operations template bool includes(InputRange1&& r1, InputRange2&& r2) { return std::includes(begin(r1), end(r1), begin(r2), end(r2)); } template bool includes(InputRange1&& r1, InputRange2&& r2, Compare comp) { return std::includes(begin(r1), end(r1), begin(r2), end(r2), comp); } template OutputIterator set_union(InputRange1&& r1, InputRange2&& r2, OutputIterator result) { return std::set_union(begin(r1), end(r1), begin(r2), end(r2), result); } template OutputIterator set_union(InputRange1&& r1, InputRange2&& r2, OutputIterator result, Compare comp) { return std::set_union(begin(r1), end(r1), begin(r2), end(r2), result, comp); } template OutputIterator set_intersection(InputRange1&& r1, InputRange2&& r2, OutputIterator result) { return std::set_intersection(begin(r1), end(r1), begin(r2), end(r2), result); } template OutputIterator set_intersection(InputRange1&& r1, InputRange2&& r2, OutputIterator result, Compare comp) { return std::set_intersection(begin(r1), end(r1), begin(r2), end(r2), result, comp); } template OutputIterator set_difference(InputRange1&& r1, InputRange2&& r2, OutputIterator result) { return std::set_difference(begin(r1), end(r1), begin(r2), end(r2), result); } template OutputIterator set_difference(InputRange1&& r1, InputRange2&& r2, OutputIterator result, Compare comp) { return std::set_difference(begin(r1), end(r1), begin(r2), end(r2), result, comp); } template OutputIterator set_symmetric_difference(InputRange1&& r1, InputRange2&& r2, OutputIterator result) { return std::set_symmetric_difference(begin(r1), end(r1), begin(r2), end(r2), result); } template OutputIterator set_symmetric_difference(InputRange1&& r1, InputRange2&& r2, OutputIterator result, Compare comp) { return std::set_symmetric_difference(begin(r1), end(r1), begin(r2), end(r2), result, comp); } // Heap operations template void push_heap(RandomAccessRange&& r) { std::push_heap(begin(r), end(r)); } template void push_heap(RandomAccessRange&& r, Compare comp) { std::push_heap(begin(r), end(r), comp); } template void pop_heap(RandomAccessRange&& r) { std::pop_heap(begin(r), end(r)); } template void pop_heap(RandomAccessRange&& r, Compare comp) { std::pop_heap(begin(r), end(r), comp); } template void make_heap(RandomAccessRange&& r) { std::make_heap(begin(r), end(r)); } template void make_heap(RandomAccessRange&& r, Compare comp) { std::make_heap(begin(r), end(r), comp); } template void sort_heap(RandomAccessRange&& r) { std::sort_heap(begin(r), end(r)); } template void sort_heap(RandomAccessRange&& r, Compare comp) { std::sort_heap(begin(r), end(r), comp); } template bool is_heap(RandomAccessRange&& r) { return std::is_heap(begin(r), end(r)); } template bool is_heap(RandomAccessRange&& r, Compare comp) { return std::is_heap(begin(r), end(r), comp); } template iterator_t is_heap_until(RandomAccessRange&& r) { return std::is_heap_until(begin(r), end(r)); } template iterator_t is_heap_until(RandomAccessRange&& r, Compare comp) { return std::is_heap_until(begin(r), end(r), comp); } // Minimum and maximum //template //T const& min(T const& a, T const& b); //template //T const& min(T const& a, T const& b, Compare comp); //template //T min(std::initializer_list t); //template //T min(std::initializer_list t, Compare comp); //template //T const& max(T const& a, T const& b); //template //T const& max(T const& a, T const& b, Compare comp); //template //T max(std::initializer_list t); //template //T max(std::initializer_list t, Compare comp); //template //std::pair minmax(T const& a, T const& b); //template //std::pair minmax(T const& a, T const& b, Compare comp); //template //std::pair minmax(std::initializer_list t); //template //std::pair minmax(std::initializer_list t, Compare comp); template iterator_t min_element(ForwardRange&& r) { return std::min_element(begin(r), end(r)); } template iterator_t min_element(ForwardRange&& r, Compare comp) { return std::min_element(begin(r), end(r), comp); } template iterator_t max_element(ForwardRange&& r) { return std::max_element(begin(r), end(r)); } template iterator_t max_element(ForwardRange&& r, Compare comp) { return std::max_element(begin(r), end(r), comp); } template std::pair, iterator_t> minmax_element(ForwardRange&& r) { return std::minmax_element(begin(r), end(r)); } template std::pair, iterator_t> minmax_element(ForwardRange&& r, Compare comp) { return std::minmax_element(begin(r), end(r), comp); } // Lexicographical comparison template bool lexicographical_compare(ForwardRange1&& r1, ForwardRange2&& r2) { return std::lexicographical_compare(begin(r1), end(r1), begin(r2), end(r2)); } template bool lexicographical_compare(ForwardRange1&& r1, ForwardRange2&& r2, Compare comp) { return std::lexicographical_compare(begin(r1), end(r1), begin(r2), end(r2), comp); } // Permutation generators template bool next_permutation(BidirectionalRange&& r) { return std::next_permutation(begin(r), end(r)); } template bool next_permutation(BidirectionalRange&& r, Compare comp) { return std::next_permutation(begin(r), end(r), comp); } template bool prev_permutation(BidirectionalRange&& r) { return std::prev_permutation(begin(r), end(r)); } template bool prev_permutation(BidirectionalRange&& r, Compare comp) { return std::prev_permutation(begin(r), end(r), comp); } // Generalized numeric operations template T accumulate(InputRange&& r, T init) { return std::accumulate(begin(r), end(r), init); } template T accumulate(InputRange&& r, T init, BinaryOperation op) { return std::accumulate(begin(r), end(r), init, op); } template T inner_product(InputRange1&& r1, InputRange2&& r2, T init) { return std::inner_product(begin(r1), end(r1), begin(r2), init); } template T inner_product(InputRange1&& r1, InputRange2&& r2, T init, BinaryOperation1 op1, BinaryOperation2 op2) { return std::inner_product(begin(r1), end(r1), begin(r2), init, op1, op2); } template OutputIterator partial_sum(InputRange&& r, OutputIterator result) { return std::partial_sum(begin(r), end(r), result); } template OutputIterator partial_sum(InputRange&& r, OutputIterator result, BinaryOperation op) { return std::partial_sum(begin(r), end(r), result, op); } template OutputIterator adjacent_difference(InputRange&& r, OutputIterator result) { return std::adjacent_difference(begin(r), end(r), result); } template OutputIterator adjacent_difference(InputRange&& r, OutputIterator result, BinaryOperation op) { return std::adjacent_difference(begin(r), end(r), result, op); } template void iota(ForwardRange&& r, T value) { std::iota(begin(r), end(r), value); } } #endif