/*  Copyright (C) 2015  Povilas Kanapickas <povilas@radix.lt>

    This file is part of cppreference-doc

    This work is licensed under the Creative Commons Attribution-ShareAlike 3.0
    Unported License. To view a copy of this license, visit
    http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative
    Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.

    Permission is granted to copy, distribute and/or modify this document
    under the terms of the GNU Free Documentation License, Version 1.3 or
    any later version published by the Free Software Foundation; with no
    Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
*/
#ifndef CPPREFERENCE_ALGORITHM_H
#define CPPREFERENCE_ALGORITHM_H

#if CPPREFERENCE_STDVER >= 2011
#include <initializer_list>
#endif

namespace std {

#if CPPREFERENCE_STDVER >= 2011
template<class InputIt, class UnaryPredicate>
bool all_of(InputIt first, InputIt last, UnaryPredicate p);

template<class InputIt, class UnaryPredicate>
bool any_of(InputIt first, InputIt last, UnaryPredicate p);

template<class InputIt, class UnaryPredicate>
bool none_of(InputIt first, InputIt last, UnaryPredicate p);
#endif

template<class InputIt, class UnaryFunction >
UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f);

template<class InputIt, class T >
typename iterator_traits<InputIt>::difference_type
count(InputIt first, InputIt last, const T& value);

template<class InputIt, class UnaryPredicate >
typename iterator_traits<InputIt>::difference_type
count_if(InputIt first, InputIt last, UnaryPredicate p);

template<class InputIt1, class InputIt2 >
std::pair<InputIt1, InputIt2>
mismatch(InputIt1 first1, InputIt1 last1,
         InputIt2 first2);

template<class InputIt1, class InputIt2, class BinaryPredicate >
std::pair<InputIt1, InputIt2>
mismatch(InputIt1 first1, InputIt1 last1,
         InputIt2 first2,
         BinaryPredicate p);

#if CPPREFERENCE_STDVER >= 2014
template<class InputIt1, class InputIt2 >
std::pair<InputIt1, InputIt2>
mismatch(InputIt1 first1, InputIt1 last1,
         InputIt2 first2, InputIt2 last2);

template<class InputIt1, class InputIt2, class BinaryPredicate >
std::pair<InputIt1, InputIt2>
mismatch(InputIt1 first1, InputIt1 last1,
         InputIt2 first2, InputIt2 last2,
         BinaryPredicate p);
#endif

template<class InputIt1, class InputIt2 >
bool equal(InputIt1 first1, InputIt1 last1,
           InputIt2 first2);

template<class InputIt1, class InputIt2, class BinaryPredicate >
bool equal(InputIt1 first1, InputIt1 last1,
           InputIt2 first2, BinaryPredicate p);

#if CPPREFERENCE_STDVER >= 2014
template<class InputIt1, class InputIt2 >
bool equal(InputIt1 first1, InputIt1 last1,
           InputIt2 first2, InputIt2 last2);

template<class InputIt1, class InputIt2, class BinaryPredicate >
bool equal(InputIt1 first1, InputIt1 last1,
           InputIt2 first2, InputIt2 last2,
           BinaryPredicate p);
#endif

template<class InputIt, class T >
InputIt find(InputIt first, InputIt last, const T& value);

template<class InputIt, class UnaryPredicate >
InputIt find_if(InputIt first, InputIt last,
                UnaryPredicate p);

#if CPPREFERENCE_STDVER >= 2011
template<class InputIt, class UnaryPredicate >
InputIt find_if_not(InputIt first, InputIt last,
                    UnaryPredicate q);
#endif

template<class ForwardIt1, class ForwardIt2 >
ForwardIt1 find_end(ForwardIt1 first, ForwardIt1 last,
                    ForwardIt2 s_first, ForwardIt2 s_last);

template<class ForwardIt1, class ForwardIt2, class BinaryPredicate >
ForwardIt1 find_end(ForwardIt1 first, ForwardIt1 last,
                    ForwardIt2 s_first, ForwardIt2 s_last, BinaryPredicate p);

#if CPPREFERENCE_STDVER >= 2011
template<class InputIt, class ForwardIt >
InputIt find_first_of(InputIt first, InputIt last,
                      ForwardIt s_first, ForwardIt s_last);

template<class InputIt, class ForwardIt, class BinaryPredicate >
InputIt find_first_of(InputIt first, InputIt last,
                      ForwardIt s_first, ForwardIt s_last, BinaryPredicate p);
#else
template<class ForwardIt1, class ForwardIt2 >
ForwardIt1 find_first_of(ForwardIt1 first, ForwardIt1 last,
                         ForwardIt2 s_first, ForwardIt2 s_last);

template<class ForwardIt1, class ForwardIt2, class BinaryPredicate >
ForwardIt1 find_first_of(ForwardIt1 first, ForwardIt1 last,
                         ForwardIt2 s_first, ForwardIt2 s_last, BinaryPredicate p);
#endif

template<class ForwardIt >
ForwardIt adjacent_find(ForwardIt first, ForwardIt last);

template<class ForwardIt, class BinaryPredicate>
ForwardIt adjacent_find(ForwardIt first, ForwardIt last, BinaryPredicate p);

template<class ForwardIt1, class ForwardIt2 >
ForwardIt1 search(ForwardIt1 first, ForwardIt1 last,
                  ForwardIt2 s_first, ForwardIt2 s_last);

template<class ForwardIt1, class ForwardIt2, class BinaryPredicate >
ForwardIt1 search(ForwardIt1 first, ForwardIt1 last,
                  ForwardIt2 s_first, ForwardIt2 s_last, BinaryPredicate p);

template<class ForwardIt, class Size, class T >
ForwardIt search_n(ForwardIt first, ForwardIt last, Size count, const T& value);

template<class ForwardIt, class Size, class T, class BinaryPredicate >
ForwardIt search_n(ForwardIt first, ForwardIt last, Size count, const T& value,
                   BinaryPredicate p);

template<class InputIt, class OutputIt >
OutputIt copy(InputIt first, InputIt last, OutputIt d_first);

#if CPPREFERENCE_STDVER >= 2011
template<class InputIt, class OutputIt, class UnaryPredicate >
OutputIt copy_if(InputIt first, InputIt last,
                 OutputIt d_first,
                 UnaryPredicate pred);
#endif

#if CPPREFERENCE_STDVER >= 2011
template<class InputIt, class Size, class OutputIt >
OutputIt copy_n(InputIt first, Size count, OutputIt result);
#endif

template<class BidirIt1, class BidirIt2 >
BidirIt2 copy_backward(BidirIt1 first, BidirIt1 last, BidirIt2 d_last);

#if CPPREFERENCE_STDVER >= 2011
template<class InputIt, class OutputIt >
OutputIt move(InputIt first, InputIt last, OutputIt d_first);
#endif

#if CPPREFERENCE_STDVER >= 2011
template<class InputIt, class OutputIt >
OutputIt move(InputIt first, InputIt last, OutputIt d_first);
#endif

template<class ForwardIt, class T >
void fill(ForwardIt first, ForwardIt last, const T& value);

#if CPPREFERENCE_STDVER >= 2011
template<class OutputIt, class Size, class T >
OutputIt fill_n(OutputIt first, Size count, const T& value);
#else
template<class OutputIt, class Size, class T >
void fill_n(OutputIt first, Size count, const T& value);
#endif

template<class InputIt, class OutputIt, class UnaryOperation >
OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first,
                   UnaryOperation unary_op);

template<class InputIt1, class InputIt2, class OutputIt, class BinaryOperation >
OutputIt transform(InputIt1 first1, InputIt1 last1, InputIt2 first2,
                   OutputIt d_first, BinaryOperation binary_op);

template<class ForwardIt, class Generator >
void generate(ForwardIt first, ForwardIt last, Generator g);

#if CPPREFERENCE_STDVER >= 2011
template<class OutputIt, class Size, class Generator >
OutputIt generate_n(OutputIt first, Size count, Generator g);
#else
template<class OutputIt, class Size, class Generator >
void generate_n(OutputIt first, Size count, Generator g);
#endif

template<class ForwardIt, class T >
ForwardIt remove(ForwardIt first, ForwardIt last, const T& value);

template<class ForwardIt, class UnaryPredicate >
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p);

template<class InputIt, class OutputIt, class T >
OutputIt remove_copy(InputIt first, InputIt last, OutputIt d_first,
                     const T& value);

template<class InputIt, class OutputIt, class UnaryPredicate >
OutputIt remove_copy_if(InputIt first, InputIt last, OutputIt d_first,
                        UnaryPredicate p);

template<class InputIt, class OutputIt, class UnaryPredicate >
OutputIt remove_copy_if(InputIt first, InputIt last, OutputIt d_first,
                        UnaryPredicate p);

template<class ForwardIt, class UnaryPredicate, class T >
void replace_if(ForwardIt first, ForwardIt last,
                UnaryPredicate p, const T& new_value);

template<class InputIt, class OutputIt, class T >
OutputIt replace_copy(InputIt first, InputIt last, OutputIt d_first,
                      const T& old_value, const T& new_value);

template<class InputIt, class OutputIt, class UnaryPredicate, class T >
OutputIt replace_copy_if(InputIt first, InputIt last, OutputIt d_first,
                         UnaryPredicate p, const T& new_value);

// defined in <utility> in C++11
#if CPPREFERENCE_STDVER >= 2011
template<class T >
void swap(T& a, T& b);
#endif

template<class ForwardIt1, class ForwardIt2 >
ForwardIt2 swap_ranges(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2);

template<class ForwardIt1, class ForwardIt2 >
void iter_swap(ForwardIt1 a, ForwardIt2 b);

template<class BidirIt >
void reverse(BidirIt first, BidirIt last);

template<class BidirIt, class OutputIt >
OutputIt reverse_copy(BidirIt first, BidirIt last, OutputIt d_first);

#if CPPREFERENCE_STDVER >= 2011
template<class ForwardIt >
ForwardIt rotate(ForwardIt first, ForwardIt n_first, ForwardIt last);
#else
template<class ForwardIt >
void rotate(ForwardIt first, ForwardIt n_first, ForwardIt last);
#endif

template<class ForwardIt, class OutputIt >
OutputIt rotate_copy(ForwardIt first, ForwardIt n_first,
                     ForwardIt last, OutputIt d_first);

#if CPPREFERENCE_STDVER <2017
// deprecated in C++14
template<class RandomIt >
void random_shuffle(RandomIt first, RandomIt last);
#endif

#if CPPREFERENCE_STDVER <2011
template<class RandomIt, class RandomFunc >
void random_shuffle(RandomIt first, RandomIt last, RandomFunc&& r);
#elif CPPREFERENCE_STDVER >= 2011 && CPPREFERENCE_STDVER <2017
// deprecated in C++14
template<class RandomIt, class RandomFunc >
void random_shuffle(RandomIt first, RandomIt last, RandomFunc& r);
#endif

#if CPPREFERENCE_STDVER >= 2011
template<class RandomIt, class URNG >
void shuffle(RandomIt first, RandomIt last, URNG&& g);
#endif

template<class ForwardIt >
ForwardIt unique(ForwardIt first, ForwardIt last);

template<class ForwardIt, class BinaryPredicate >
ForwardIt unique(ForwardIt first, ForwardIt last, BinaryPredicate p);

template<class InputIt, class OutputIt >
OutputIt unique_copy(InputIt first, InputIt last,
                     OutputIt d_first);

template<class InputIt, class OutputIt, class BinaryPredicate >
OutputIt unique_copy(InputIt first, InputIt last,
                     OutputIt d_first, BinaryPredicate p);

#if CPPREFERENCE_STDVER >= 2011
template<class InputIt, class UnaryPredicate >
bool is_partitioned(InputIt first, InputIt last, UnaryPredicate p);
#endif

#if CPPREFERENCE_STDVER <2011
template<class BidirIt, class UnaryPredicate >
BidirIt partition(BidirIt first, BidirIt last, UnaryPredicate p);
#else
template<class ForwardIt, class UnaryPredicate >
ForwardIt partition(ForwardIt first, ForwardIt last, UnaryPredicate p);
#endif

#if CPPREFERENCE_STDVER >= 2011
template<class InputIt, class OutputIt1,
         class OutputIt2, class UnaryPredicate >
std::pair<OutputIt1, OutputIt2>
partition_copy(InputIt first, InputIt last,
               OutputIt1 d_first_true, OutputIt2 d_first_false,
               UnaryPredicate p);
#endif

template<class BidirIt, class UnaryPredicate >
BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);

#if CPPREFERENCE_STDVER >= 2011
template<class ForwardIt, class UnaryPredicate >
ForwardIt partition_point(ForwardIt first, ForwardIt last, UnaryPredicate p);
#endif

#if CPPREFERENCE_STDVER >= 2011
template<class ForwardIt >
bool is_sorted(ForwardIt first, ForwardIt last);

template<class ForwardIt, class Compare >
bool is_sorted(ForwardIt first, ForwardIt last, Compare comp);

template<class ForwardIt >
ForwardIt is_sorted_until(ForwardIt first, ForwardIt last);

template<class ForwardIt, class Compare >
ForwardIt is_sorted_until(ForwardIt first, ForwardIt last,
                          Compare comp);
#endif

template<class RandomIt >
void sort(RandomIt first, RandomIt last);

template<class RandomIt, class Compare >
void sort(RandomIt first, RandomIt last, Compare comp);

template<class RandomIt >
void partial_sort(RandomIt first, RandomIt middle, RandomIt last);

template<class RandomIt, class Compare >
void partial_sort(RandomIt first, RandomIt middle, RandomIt last, Compare comp);

template<class InputIt, class RandomIt >
RandomIt partial_sort_copy(InputIt first, InputIt last,
                           RandomIt d_first, RandomIt d_last);

template<class InputIt, class RandomIt, class Compare >
RandomIt partial_sort_copy(InputIt first, InputIt last,
                           RandomIt d_first, RandomIt d_last,
                           Compare comp);

template<class RandomIt >
void stable_sort(RandomIt first, RandomIt last);

template<class RandomIt, class Compare >
void stable_sort(RandomIt first, RandomIt last, Compare comp);

template<class RandomIt >
void nth_element(RandomIt first, RandomIt nth, RandomIt last);

template<class RandomIt, class Compare >
void nth_element(RandomIt first, RandomIt nth, RandomIt last, Compare comp);

template<class ForwardIt, class T >
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value);

template<class ForwardIt, class T, class Compare >
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp);

template<class ForwardIt, class T >
ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value);

template<class ForwardIt, class T, class Compare >
ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp);

template<class ForwardIt, class T >
bool binary_search(ForwardIt first, ForwardIt last, const T& value);

template<class ForwardIt, class T, class Compare >
bool binary_search(ForwardIt first, ForwardIt last, const T& value, Compare comp);

template<class ForwardIt, class T >
std::pair<ForwardIt, ForwardIt>
equal_range(ForwardIt first, ForwardIt last,
            const T& value);

template<class ForwardIt, class T, class Compare >
std::pair<ForwardIt, ForwardIt>
equal_range(ForwardIt first, ForwardIt last,
            const T& value, Compare comp);

template<class InputIt1, class InputIt2, class OutputIt >
OutputIt merge(InputIt1 first1, InputIt1 last1,
               InputIt2 first2, InputIt2 last2,
               OutputIt d_first);

template<class InputIt1, class InputIt2, class OutputIt, class Compare>
OutputIt merge(InputIt1 first1, InputIt1 last1,
               InputIt2 first2, InputIt2 last2,
               OutputIt d_first, Compare comp);

template<class BidirIt >
void inplace_merge(BidirIt first, BidirIt middle, BidirIt last);

template<class BidirIt, class Compare>
void inplace_merge(BidirIt first, BidirIt middle, BidirIt last, Compare comp);

template<class InputIt1, class InputIt2 >
bool includes(InputIt1 first1, InputIt1 last1,
              InputIt2 first2, InputIt2 last2);

template<class InputIt1, class InputIt2, class Compare >
bool includes(InputIt1 first1, InputIt1 last1,
              InputIt2 first2, InputIt2 last2, Compare comp);

template<class InputIt1, class InputIt2, class OutputIt >
OutputIt set_difference(InputIt1 first1, InputIt1 last1,
                        InputIt2 first2, InputIt2 last2,
                        OutputIt d_first);

template<class InputIt1, class InputIt2,
         class OutputIt, class Compare >
OutputIt set_difference(InputIt1 first1, InputIt1 last1,
                        InputIt2 first2, InputIt2 last2,
                        OutputIt d_first, Compare comp);

template<class InputIt1, class InputIt2, class OutputIt >
OutputIt set_intersection(InputIt1 first1, InputIt1 last1,
                          InputIt2 first2, InputIt2 last2,
                          OutputIt d_first);

template<class InputIt1, class InputIt2,
         class OutputIt, class Compare >
OutputIt set_intersection(InputIt1 first1, InputIt1 last1,
                          InputIt2 first2, InputIt2 last2,
                          OutputIt d_first, Compare comp);

template<class InputIt1, class InputIt2, class OutputIt >
OutputIt set_symmetric_difference(InputIt1 first1, InputIt1 last1,
                                  InputIt2 first2, InputIt2 last2,
                                  OutputIt d_first);

template<class InputIt1, class InputIt2,
         class OutputIt, class Compare >
OutputIt set_symmetric_difference(InputIt1 first1, InputIt1 last1,
                                  InputIt2 first2, InputIt2 last2,
                                  OutputIt d_first, Compare comp);

template<class InputIt1, class InputIt2, class OutputIt >
OutputIt set_union(InputIt1 first1, InputIt1 last1,
                   InputIt2 first2, InputIt2 last2,
                   OutputIt d_first);

template<class InputIt1, class InputIt2,
         class OutputIt, class Compare >
OutputIt set_union(InputIt1 first1, InputIt1 last1,
                   InputIt2 first2, InputIt2 last2,
                   OutputIt d_first, Compare comp);

#if CPPREFERENCE_STDVER >= 2011
template<class RandomIt >
bool is_heap(RandomIt first, RandomIt last);

template<class RandomIt, class Compare >
bool is_heap(RandomIt first, RandomIt last, Compare comp);

template<class RandomIt >
RandomIt is_heap_until(RandomIt first, RandomIt last);

template<class RandomIt, class Compare >
RandomIt is_heap_until(RandomIt first, RandomIt last, Compare comp);
#endif

template<class RandomIt >
void make_heap(RandomIt first, RandomIt last);

template<class RandomIt, class Compare >
void make_heap(RandomIt first, RandomIt last,
               Compare comp);

template<class RandomIt >
void push_heap(RandomIt first, RandomIt last);

template<class RandomIt, class Compare >
void push_heap(RandomIt first, RandomIt last,
               Compare comp);

template<class RandomIt >
void pop_heap(RandomIt first, RandomIt last);

template<class RandomIt, class Compare >
void pop_heap(RandomIt first, RandomIt last, Compare comp);

template<class RandomIt >
void sort_heap(RandomIt first, RandomIt last);

template<class RandomIt, class Compare >
void sort_heap(RandomIt first, RandomIt last, Compare comp);

#if CPPREFERENCE_STDVER <2014
template<class T >
const T& max(const T& a, const T& b);

template<class T, class Compare >
const T& max(const T& a, const T& b, Compare comp);
#else
template<class T >
constexpr const T& max(const T& a, const T& b);

template<class T, class Compare >
constexpr const T& max(const T& a, const T& b, Compare comp);
#endif

#if CPPREFERENCE_STDVER >= 2011
template<class T >
T max(std::initializer_list<T> ilist);

template<class T, class Compare >
T max(std::initializer_list<T> ilist, Compare comp);
#elif CPPREFERENCE_STDVER >= 2014
template<class T >
constexpr T max(std::initializer_list<T> ilist);

template<class T, class Compare >
constexpr T max(std::initializer_list<T> ilist, Compare comp);
#endif

#if CPPREFERENCE_STDVER <2017
template<class ForwardIt >
ForwardIt max_element(ForwardIt first, ForwardIt last);

template<class ForwardIt, class Compare >
ForwardIt max_element(ForwardIt first, ForwardIt last, Compare cmp);
#else
template<class ForwardIt >
constexpr ForwardIt max_element(ForwardIt first, ForwardIt last);

template<class ForwardIt, class Compare >
constexpr ForwardIt max_element(ForwardIt first, ForwardIt last, Compare cmp);
#endif

#if CPPREFERENCE_STDVER <2014
template<class T >
const T& min(const T& a, const T& b);

template<class T, class Compare >
const T& min(const T& a, const T& b, Compare comp);
#else
template<class T >
constexpr const T& min(const T& a, const T& b);

template<class T, class Compare >
constexpr const T& min(const T& a, const T& b, Compare comp);
#endif

#if CPPREFERENCE_STDVER >= 2011
template<class T >
T min(std::initializer_list<T> ilist);

template<class T, class Compare >
T min(std::initializer_list<T> ilist, Compare comp);
#elif CPPREFERENCE_STDVER >= 2014
template<class T >
constexpr T min(std::initializer_list<T> ilist);

template<class T, class Compare >
constexpr T min(std::initializer_list<T> ilist, Compare comp);
#endif

#if CPPREFERENCE_STDVER <2017
template<class ForwardIt >
ForwardIt min_element(ForwardIt first, ForwardIt last);

template<class ForwardIt, class Compare >
ForwardIt min_element(ForwardIt first, ForwardIt last, Compare cmp);
#else
template<class ForwardIt >
constexpr ForwardIt min_element(ForwardIt first, ForwardIt last);

template<class ForwardIt, class Compare >
constexpr ForwardIt min_element(ForwardIt first, ForwardIt last, Compare cmp);
#endif

#if CPPREFERENCE_STDVER >= 2011 && CPPREFERENCE_STDVER <2014
template<class T >
std::pair<const T&, const T&> minmax(const T& a, const T& b);

template<class T, class Compare >
std::pair<const T&, const T&> minmax(const T& a, const T& b,
                                     Compare comp);

template<class T >
std::pair<T, T> minmax(std::initializer_list<T> ilist);

template<class T, class Compare >
std::pair<T, T> minmax(std::initializer_list<T> ilist, Compare comp);

#elif CPPREFERENCE_STDVER >= 2014
template<class T >
constexpr std::pair<const T&, const T&> minmax(const T& a, const T& b);

template<class T, class Compare >
constexpr std::pair<const T&, const T&> minmax(const T& a, const T& b,
        Compare comp);
template<class T >
constexpr std::pair<T, T> minmax(std::initializer_list<T> ilist);

template<class T, class Compare >
constexpr std::pair<T, T> minmax(std::initializer_list<T> ilist, Compare comp);
#endif

#if CPPREFERENCE_STDVER >= 2011 && CPPREFERENCE_STDVER <2017
template<class ForwardIt >
std::pair<ForwardIt, ForwardIt>
minmax_element(ForwardIt first, ForwardIt last);

template<class ForwardIt, class Compare >
std::pair<ForwardIt, ForwardIt>
minmax_element(ForwardIt first, ForwardIt last, Compare comp);
#elif CPPREFERENCE_STDVER >= 2017
template<class ForwardIt >
constexpr std::pair<ForwardIt, ForwardIt>
minmax_element(ForwardIt first, ForwardIt last);

template<class ForwardIt, class Compare >
constexpr std::pair<ForwardIt, ForwardIt>
minmax_element(ForwardIt first, ForwardIt last, Compare comp);
#endif

template<class InputIt1, class InputIt2 >
bool lexicographical_compare(InputIt1 first1, InputIt1 last1,
                             InputIt2 first2, InputIt2 last2);

template<class InputIt1, class InputIt2, class Compare >
bool lexicographical_compare(InputIt1 first1, InputIt1 last1,
                             InputIt2 first2, InputIt2 last2,
                             Compare comp);

#if CPPREFERENCE_STDVER >= 2011
template<class ForwardIt1, class ForwardIt2 >
bool is_permutation(ForwardIt1 first1, ForwardIt1 last1,
                    ForwardIt2 first2);

template<class ForwardIt1, class ForwardIt2, class BinaryPredicate >
bool is_permutation(ForwardIt1 first1, ForwardIt1 last1,
                    ForwardIt2 first2, BinaryPredicate p);
#endif

#if CPPREFERENCE_STDVER >= 2011
template<class ForwardIt1, class ForwardIt2 >
bool is_permutation(ForwardIt1 first1, ForwardIt1 last1,
                    ForwardIt2 first2, ForwardIt2 last2);

template<class ForwardIt1, class ForwardIt2, class BinaryPredicate >
bool is_permutation(ForwardIt1 first1, ForwardIt1 last1,
                    ForwardIt2 first2, ForwardIt2 last2,
                    BinaryPredicate p);
#endif

template<class BidirIt >
bool next_permutation(BidirIt first, BidirIt last);

template<class BidirIt, class Compare >
bool next_permutation(BidirIt first, BidirIt last, Compare comp);

template<class BidirIt >
bool prev_permutation(BidirIt first, BidirIt last);

template<class BidirIt, class Compare >
bool prev_permutation(BidirIt first, BidirIt last, Compare comp);

} // namespace std

#endif // CPPREFERENCE_ALGORITHM_H
