読者です 読者をやめる 読者になる 読者になる

SFINAE版STLアルゴリズム 〜begin/endにさようなら〜

C++

こっちが最新です


SFINAEで実装したSTLアルゴリズムです


これを使うと以下のように書けます

vector<int> v;

sort(v); // begin/endではなくコンテナ/配列を直接渡す


ソースは以下(※めっちゃ長い)

// SFINAEをサポートしているコンパイラか?
#if !defined(_MSC_VER) || (_MSC_VER > 1300)  // 1300 == VC++ 7.0
    #define SHAND_SUPPORT_SFINAE
#endif


namespace shand {

#ifdef SHAND_SUPPORT_SFINAE

namespace algorithm_detail {

// STL Container
struct sfinae_types {
    typedef char yes;
    typedef struct { char arr[2]; } no;
};

template <class Type>
struct is_stl : sfinae_types {
private:
    template <class Type>
    static yes check(typename Type::iterator*);

    template<class>
    static no check(...);
public:
    enum { value = sizeof(yes)==sizeof(check<Type>(0)) };
};


// enable_if
template <bool, class Type = void>
struct enable_if_c {
    typedef Type type;
};

template <class Type>
struct enable_if_c<false, Type> {};

template <class Cond, class Type = void>
struct enable_if : public enable_if_c<Cond::value, Type> {};


} // namespace shand::algorithm_detail


#define IS_STL(Container) typename algorithm_detail::enable_if<algorithm_detail::is_stl<Container> >::type* = 0

#endif // SHAND_SUPPORT_SFINAE




#ifdef SHAND_SUPPORT_SFINAE

// for_each
template <class Type, int Size, class Predicate>
inline Predicate for_each(Type (&ar)[Size], Predicate pred, void* = 0)
{
    return std::for_each(ar, ar + Size, pred);
}

template <class Container, class Predicate>
inline Predicate for_each(Container &container, Predicate pred, IS_STL(Container))
{
    return std::for_each(container.begin(), container.end(), pred);
}

template <class Container, class Predicate>
inline Predicate for_each(const Container &container, Predicate pred, IS_STL(Container))
{
    return std::for_each(container.begin(), container.end(), pred);
}


// find
template <class Type, int Size, class Target>
inline Type* find(Type (&ar)[Size], const Target& value, void* = 0)
{
    return std::find(ar, ar + Size, value);
}

template <class Container, class Target>
inline typename Container::iterator find(Container &container, const Target& value, IS_STL(Container))
{
    return std::find(container.begin(), container.end(), value);
}

template <class Container, class Target>
inline typename Container::const_iterator find(const Container &container, const Target& value, IS_STL(Container))
{
    return std::find(container.begin(), container.end(), value);
}


// find_if
template <class Type, int Size, class Predicate>
inline Type* find_if(Type (&ar)[Size], Predicate pred, void* = 0)
{
    return std::find_if(ar, ar + Size, pred);
}

template <class Container, class Predicate>
inline typename Container::iterator find_if(Container& container, Predicate pred, IS_STL(Container))
{
    return std::find_if(container.begin(), container.end(), pred);
}

template <class Container, class Predicate>
inline typename Container::const_iterator find_if(const Container& container, Predicate pred, IS_STL(Container))
{
    return std::find_if(container.begin(), container.end(), pred);
}


// find_first_of
template <class LType, int LSize, class RType, int RSize>
inline LType* find_first_of(LType (&lhs)[LSize], RType (&rhs)[RSize], void* = 0)
{
    return std::find_first_of(lhs, lhs + LSize, rhs, rhs + RSize);
}

template <class LType, int LSize, class RType, int RSize, class Predicate>
inline LType* find_first_of(LType (&lhs)[LSize], RType (&rhs)[RSize], Predicate pred, void* = 0)
{
    return std::find_first_of(lhs, lhs + LSize, rhs, rhs + RSize, pred);
}

template <class LContainer, class RContainer>
inline typename LContainer::iterator find_first_of(LContainer &lhs, RContainer &rhs, IS_STL(LContainer))
{
    return std::find_first_of(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}

template <class LContainer, class RContainer, class Predicate>
inline typename LContainer::iterator find_first_of(LContainer &lhs, RContainer &rhs, Predicate pred, IS_STL(LContainer))
{
    return std::find_first_of(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), pred);
}

template <class LContainer, class RContainer>
inline typename LContainer::const_iterator find_first_of(const LContainer& lhs, const RContainer& rhs, IS_STL(LContainer))
{
    return std::find_first_of(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}

template <class LContainer, class RContainer, class Predicate>
inline typename LContainer::const_iterator find_first_of(const LContainer& lhs, const RContainer& rhs, Predicate pred, IS_STL(LContainer))
{
    return std::find_first_of(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), pred);
}


// find_end
template <class LType, int LSize, class RType, int RSize>
inline LType*
find_end(LType (&lhs)[LSize], RType (&rhs)[RSize], void* = 0)
{
    return std::find_end(lhs, lhs + LSize, rhs, rhs + RSize);
}

template <class LType, int LSize, class RType, int RSize, class Predicate>
inline LType* find_end(LType (&lhs)[LSize], RType (&rhs)[RSize], Predicate pred, void* = 0)
{
    return std::find_end(lhs, lhs + LSize, rhs, rhs + RSize, pred);
}

template <class LContainer, class RContainer>
inline typename LContainer::iterator find_end(LContainer &lhs, RContainer &rhs, IS_STL(LContainer))
{
    return std::find_end(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}

template <class LContainer, class RContainer, class Predicate>
inline typename LContainer::iterator find_end(LContainer &lhs, RContainer &rhs, Predicate pred, IS_STL(LContainer))
{
    return std::find_end(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), pred);
}

template <class LContainer, class RContainer>
inline typename LContainer::const_iterator find_end(const LContainer& lhs, const RContainer& rhs, IS_STL(LContainer))
{
    return std::find_end(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}

template <class LContainer, class RContainer, class Predicate>
inline typename LContainer::const_iterator find_end(const LContainer& lhs, const RContainer& rhs, Predicate pred, IS_STL(LContainer))
{
    return std::find_end(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), pred);
}


// adjacent_find
template <class Type, int Size>
inline Type* adjacent_find(Type (&ar)[Size], void* = 0)
{
    return std::adjacent_find(ar, ar + Size);
}

template <class Type, int Size, class Predicate>
inline Type* adjacent_find(Type (&ar)[Size], Predicate pred, void* = 0)
{
    return std::adjacent_find(ar, ar + Size, pred);
}

template <class Container>
inline typename Container::iterator adjacent_find(Container& container, IS_STL(Container))
{
    return std::adjacent_find(container.begin(), container.end());
}

template <class Container>
inline typename Container::const_iterator adjacent_find(const Container& container, IS_STL(Container))
{
    return std::adjacent_find(container.begin(), container.end());
}

template <class Container, class Predicate>
inline typename Container::iterator adjacent_find(Container& container, Predicate pred, IS_STL(Container))
{
    return std::adjacent_find(container.begin(), container.end(), pred);
}

template <class Container, class Predicate>
inline typename Container::const_iterator adjacent_find(const Container& container, Predicate pred, IS_STL(Container))
{
    return std::adjacent_find(container.begin(), container.end(), pred);
}


// count
template <class Type, int Size, class Target>
inline Type count(Type (&ar)[Size], const Target& value, void* = 0)
{
    return std::count(ar, ar + Size, value);
}

template <class Container, class Target>
inline typename Container::difference_type count(const Container& container, const Target& value, IS_STL(Container))
{
    return std::count(container.begin(), container.end(), value);
}


// count_if
template <class Type, int Size, class Predicate>
inline Type count_if(Type (&ar)[Size], Predicate pred, void* = 0)
{
    return std::count_if(ar, ar + Size, pred);
}

template <class Container, class Predicate>
inline typename Container::difference_type count_if(const Container& container, Predicate pred, IS_STL(Container))
{
    return std::count_if(container.begin(), container.end(), pred);
}


// mismatch
template <class Type, int Size, class InputIterator>
inline std::pair<Type*, InputIterator> mismatch(Type (&ar)[Size], InputIterator first, void* = 0)
{
    return std::mismatch(ar, ar + Size, first);
}

template <class Type, int Size, class InputIterator, class Predicate>
inline std::pair<Type*, InputIterator> mismatch(Type (&ar)[Size], InputIterator first, Predicate pred, void* = 0)
{
    return std::mismatch(ar, ar + Size, first, pred);
}

template <class Container, class InputIterator>
inline std::pair<typename Container::iterator, InputIterator>
mismatch(Container& container, InputIterator first, IS_STL(Container))
{
    return std::mismatch(container.begin(), container.end(), first);
}

template <class Container, class InputIterator, class Predicate>
inline std::pair<typename Container::iterator, InputIterator>
mismatch(Container& container, InputIterator first, Predicate pred, IS_STL(Container))
{
    return std::mismatch(container.begin(), container.end(), first, pred);
}

template <class Container, class InputIterator>
inline std::pair<typename Container::const_iterator, InputIterator>
mismatch(const Container& container, InputIterator first, IS_STL(Container))
{
    return std::mismatch(container.begin(), container.end(), first);
}

template <class Container, class InputIterator, class Predicate>
inline std::pair<typename Container::const_iterator, InputIterator>
mismatch(const Container& container, InputIterator first, Predicate pred, IS_STL(Container))
{
    return std::mismatch(container.begin(), container.end(), first, pred);
}

// equal
template <class Type, int Size, class InputIterator>
inline bool equal(Type (&ar)[Size], InputIterator first, void* = 0)
{
    return std::equal(ar, ar + Size, first);
}

template <class Type, int Size, class InputIterator, class Predicate>
inline bool equal(Type (&ar)[Size], InputIterator first, Predicate pred, void* = 0)
{
    return std::equal(ar, ar + Size, first, pred);
}

template <class Container, class InputIterator>
inline bool equal(const Container& container, InputIterator first, IS_STL(Container))
{
    return std::equal(container.begin(), container.end(), first);
}

template <class Container, class InputIterator, class Predicate>
inline bool equal(const Container& container, InputIterator first, Predicate pred, IS_STL(Container))
{
    return std::equal(container.begin(), container.end(), first, pred);
}

// search
template <class LType, int LSize, class RType, int RSize>
inline LType* search(LType (&lhs)[LSize], RType (&rhs)[RSize], void* = 0)
{
    return std::search(lhs, lhs + LSize, rhs, rhs + RSize);
}

template <class LType, int LSize, class RType, int RSize, class BynaryPredicate>
inline LType* search(LType (&lhs)[LSize], RType (&rhs)[RSize], BynaryPredicate pred, void* = 0)
{
    return std::search(lhs, lhs + LSize, rhs, rhs + RSize, pred);
}

template <class LContainer, class RContainer>
inline typename LContainer::iterator search(LContainer& lhs, RContainer& rhs, IS_STL(LContainer))
{
    return std::search(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}

template <class LContainer, class RContainer, class BynaryPredicate>
inline typename LContainer::iterator search(LContainer& lhs, RContainer& rhs, BynaryPredicate pred, IS_STL(LContainer))
{
    return std::search(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), pred);
}

template <class LContainer, class RContainer>
inline typename LContainer::const_iterator search(const LContainer& lhs, const RContainer& rhs, IS_STL(LContainer))
{
    return std::search(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}

template <class LContainer, class RContainer, class BynaryPredicate>
inline typename LContainer::const_iterator search(const LContainer& lhs, const RContainer& rhs, BynaryPredicate pred, IS_STL(LContainer))
{
    return std::search(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), pred);
}

// copy
template <class Type, int Size, class OutputIterator>
inline OutputIterator copy(Type (&ar)[Size], OutputIterator result, void* = 0)
{
    return std::copy(ar, ar + Size, result);
}

template <class Container, class OutputIterator>
inline OutputIterator copy(const Container& container, OutputIterator result, IS_STL(Container))
{
    return std::copy(container.begin(), container.end(), result);
}


// copy_backward
template <class Type, int Size, class BidirectionalIterator>
inline BidirectionalIterator copy_backward(Type (&ar)[Size], BidirectionalIterator result, void* = 0)
{
    return std::copy_backward(ar, ar + Size, result);
}

template <class Container, class BidirectionalIterator>
inline BidirectionalIterator copy_backward(const Container& container, BidirectionalIterator result, IS_STL(Container))
{
    return std::copy_backward(container.begin(), container.end(), result);
}


// transform
template <class Type, int Size, class OutputIterator, class UnaryOperation>
inline OutputIterator transform(Type (&ar)[Size], OutputIterator result, UnaryOperation op, void* = 0)
{
    return std::transform(ar, ar + Size, result, op);
}

template <class Type, int Size, class InputIterator, class OutputIterator, class BynaryOperation>
inline OutputIterator transform(Type (&ar)[Size], InputIterator first, OutputIterator result, BynaryOperation op, void* = 0)
{
    return std::transform(ar, ar + Size, first, result, op);
}

template <class Container, class OutputIterator, class UnaryOperation>
inline OutputIterator transform(const Container& container, OutputIterator result, UnaryOperation op, IS_STL(Container))
{
    return std::transform(container.begin(), container.end(), result, op);
}

template <class Container, class InputIterator, class OutputIterator, class BynaryOperation>
inline OutputIterator transform(const Container& container, InputIterator first, OutputIterator result, BynaryOperation op, IS_STL(Container))
{
    return std::transform(container.begin(), container.end(), first, result, op);
}


// replace
template <class Type, int Size, class Target>
inline void replace(Type (&ar)[Size], const Target& old_value, const Target& new_value, void* = 0)
{
    std::replace(ar, ar + Size, old_value, new_value);
}

template <class Container, class Target>
inline void replace(Container& container, const Target& old_value, const Target& new_value, IS_STL(Container))
{
    std::replace(container.begin(), container.end(), old_value, new_value);
}


// replace_if
template <class Type, int Size, class Predicate, class Target>
inline void replace_if(Type (&ar)[Size], Predicate pred, const Target& new_value, void* = 0)
{
    std::replace_if(ar, ar + Size, pred, new_value);
}

template <class Container, class Predicate, class Target>
inline void replace_if(Container& container, Predicate pred, const Target& new_value, IS_STL(Container))
{
    std::replace_if(container.begin(), container.end(), pred, new_value);
}


// replace_copy
template <class Type, int Size, class OutputIterator, class Target>
inline OutputIterator
replace_copy(Type (&ar)[Size], OutputIterator result, const Target& old_value, const Target& new_value, void* = 0)
{
    return std::replace_copy(ar, ar + Size, result, old_value, new_value);
}

template <class Container, class OutputIterator, class Target>
inline OutputIterator
replace_copy(const Container& container, OutputIterator result, const Target& old_value, const Target& new_value, IS_STL(Container))
{
    return std::replace_copy(container.begin(), container.end(), result, old_value, new_value);
}


// replace_copy_if
template <class Type, int Size, class OutputIterator, class Predicate, class Target>
inline OutputIterator
replace_copy_if(Type (&ar)[Size], OutputIterator result, Predicate pred, const Target& new_value, void* = 0)
{
    return std::replace_copy_if(ar, ar + Size, result, pred, new_value);
}

template <class Container, class OutputIterator, class Predicate, class Target>
inline OutputIterator
replace_copy_if(const Container& container, OutputIterator result, Predicate pred, const Target& new_value, IS_STL(Container))
{
    return std::replace_copy_if(container.begin(), container.end(), result, pred, new_value);
}


// fill
template <class Type, int Size, class Target>
inline void fill(Type (&ar)[Size], const Target& value, void* = 0)
{
    std::fill(ar, ar + Size, value);
}

template <class Container, class Target>
inline void fill(Container& container, const Target& value, IS_STL(Container))
{
    std::fill(container.begin(), container.end(), value);
}


// generate
template <class Type, int Size, class Generator>
inline void generate(Type (&ar)[Size], Generator gen, void* = 0)
{
    return std::generate(ar, ar + Size, gen);
}

template <class Container, class Generator>
inline void generate(Container &container, Generator gen, IS_STL(Container))
{
    return std::generate(container.begin(), container.end(), gen);
}


// remove
template <class Type, int Size, class Target>
inline Type* remove(Type (&ar)[Size], const Target& value, void* = 0)
{
    return std::remove(ar, ar + Size, value);
}

template <class Container, class Target>
inline typename Container::iterator remove(Container& container, const Target& value, IS_STL(Container))
{
    return std::remove(container.begin(), container.end(), value);
}

// remove_if
template <class Type, int Size, class Predicate>
inline Type* remove_if(Type (&ar)[Size], Predicate pred, void* = 0)
{
    return std::remove_if(ar, ar + Size, pred);
}

template <class Container, class Predicate>
inline typename Container::iterator remove_if(Container& container, Predicate pred, IS_STL(Container))
{
    return std::remove_if(container.begin(), container.end(), pred);
}

// remove_copy
template <class Type, int Size, class OutputIterator, class Target>
inline OutputIterator remove_copy(Type (&ar)[Size], OutputIterator result, const Target& value, void* = 0)
{
    return std::remove_copy(ar, ar + Size, result, value);
}

template <class Container, class OutputIterator, class Target>
inline OutputIterator remove_copy(const Container& container, OutputIterator result, const Target& value, IS_STL(Container))
{
    return std::remove_copy(container.begin(), container.end(), result, value);
}

// remove_copy_if
template <class Type, int Size, class OutputIterator, class Predicate>
inline OutputIterator remove_copy_if(Type (&ar)[Size], OutputIterator result, Predicate pred, void* = 0)
{
    return std::remove_copy_if(ar, ar + Size, result, pred);
}

template <class Container, class OutputIterator, class Predicate>
inline OutputIterator remove_copy_if(const Container& container, OutputIterator result, Predicate pred, IS_STL(Container))
{
    return std::remove_copy_if(container.begin(), container.end(), result, pred);
}

// unique
template <class Type, int Size>
inline Type* unique(Type (&ar)[Size], void* = 0)
{
    return std::unique(ar, ar + Size);
}

template <class Type, int Size, class BynaryPredicate>
inline Type* unique(Type (&ar)[Size], BynaryPredicate pred, void* = 0)
{
    return std::unique(ar, ar + Size, pred);
}

template <class Container>
inline typename Container::iterator unique(Container& container, IS_STL(Container))
{
    return std::unique(container.begin(), container.end());
}

template <class Container, class BynaryPredicate>
inline typename Container::iterator unique(Container& container, BynaryPredicate pred, IS_STL(Container))
{
    return std::unique(container.begin(), container.end(), pred);
}

// unique_copy
template <class Type, int Size, class OutputIterator>
inline OutputIterator unique_copy(Type (&ar)[Size], OutputIterator result, void* = 0)
{
    return std::unique_copy(ar, ar + Size, result);
}

template <class Type, int Size, class OutputIterator, class BynaryPredicate>
inline OutputIterator unique_copy(Type (&ar)[Size], OutputIterator result, BynaryPredicate pred, void* = 0)
{
    return std::unique_copy(ar, ar + Size, result, pred);
}

template <class Container, class OutputIterator>
inline OutputIterator unique_copy(const Container& container, OutputIterator result, IS_STL(Container))
{
    return std::unique_copy(container.begin(), container.end(), result);
}

template <class Container, class OutputIterator, class BynaryPredicate>
inline OutputIterator unique_copy(const Container& container, OutputIterator result, BynaryPredicate pred, IS_STL(Container))
{
    return std::unique_copy(container.begin(), container.end(), result, pred);
}

// reverse
template <class Type, int Size>
inline void reverse(Type (&ar)[Size], void* = 0)
{
    std::reverse(ar, ar + Size);
}

template <class Container>
inline void reverse(Container& container, IS_STL(Container))
{
    std::reverse(container.begin(), container.end());
}

// reverse_copy
template <class Type, int Size, class OutputIterator>
inline OutputIterator reverse_copy(Type (&ar)[Size], OutputIterator result, void* = 0)
{
    return std::reverse_copy(ar, ar + Size, result);
}

template <class Container, class OutputIterator>
inline OutputIterator reverse_copy(Container& container, OutputIterator result, IS_STL(Container))
{
    return std::reverse_copy(container.begin(), container.end(), result);
}

// random_shuffle
template <class Type, int Size>
inline void random_shuffle(Type (&ar)[Size], void* = 0)
{
    std::random_shuffle(ar, ar + Size);
}

template <class Type, int Size, class RandomNumberGenerator>
inline void random_shuffle(Type (&ar)[Size], RandomNumberGenerator& gen, void* = 0)
{
    std::random_shuffle(ar, ar + Size, gen);
}

template <class Container>
inline void random_shuffle(Container &container, IS_STL(Container))
{
    std::random_shuffle(container.begin(), container.end());
}

template <class Container, class RandomNumberGenerator>
inline void random_shuffle(Container &container, RandomNumberGenerator& gen, IS_STL(Container))
{
    std::random_shuffle(container.begin(), container.end(), gen);
}

// partition
template <class Type, int Size, class Predicate>
inline Type* partition(Type (&ar)[Size], Predicate pred, void* = 0)
{
    return std::partition(ar, ar + Size, pred);
}

template <class Container, class Predicate>
inline typename Container::iterator partition(Container& container, Predicate pred, IS_STL(Container))
{
    return std::partition(container.begin(), container.end(), pred);
}

// stable_partition
template <class Type, int Size, class Predicate>
inline Type* stable_partition(Type (&ar)[Size], Predicate pred, void* = 0)
{
    return std::stable_partition(ar, ar + Size, pred);
}

template <class Container, class Predicate>
inline typename Container::iterator stable_partition(Container& container, Predicate pred, IS_STL(Container))
{
    return std::stable_partition(container.begin(), container.end(), pred);
}

// sort
template <class Type, int Size>
inline void sort(Type (&ar)[Size], void* = 0)
{
    std::sort(ar, ar + Size);
}

template <class Type, int Size, class Compare>
inline void sort(Type (&ar)[Size], Compare comp, void* = 0)
{
    std::sort(ar, ar + Size, comp);
}

template <class Container>
inline void sort(Container &container, IS_STL(Container))
{
    std::sort(container.begin(), container.end());
}

template <class Container, class Compare>
inline void sort(Container &container, Compare comp, IS_STL(Container))
{
    std::sort(container.begin(), container.end(), comp);
}

// stable_sort
template <class Type, int Size>
inline void stable_sort(Type (&ar)[Size], void* = 0)
{
    std::stable_sort(ar, ar + Size);
}

template <class Type, int Size, class Compare>
inline void stable_sort(Type (&ar)[Size], Compare comp, void* = 0)
{
    std::stable_sort(ar, ar + Size, comp);
}

template <class Container>
inline void stable_sort(Container &container, IS_STL(Container))
{
    std::stable_sort(container.begin(), container.end());
}

template <class Container, class Compare>
inline void stable_sort(Container &container, Compare comp, IS_STL(Container))
{
    std::stable_sort(container.begin(), container.end(), comp);
}

// lower_bound
template <class Type, int Size, class Target>
inline Type* lower_bound(Type (&ar)[Size], const Target& value, void* = 0)
{
    return std::lower_bound(ar, ar + Size, value);
}

template <class Type, int Size, class Target, class Compare>
inline Type* lower_bound(Type (&ar)[Size], const Target& value, Compare comp, void* = 0)
{
    return std::lower_bound(ar, ar + Size, value, comp);
}

template <class Container, class Target>
inline typename Container::iterator lower_bound(Container& container, const Target& value, IS_STL(Container))
{
    return std::lower_bound(container.begin(), container.end(), value);
}

template <class Container, class Target, class Compare>
inline typename Container::iterator lower_bound(Container& container, const Target& value, Compare comp, IS_STL(Container))
{
    return std::lower_bound(container.begin(), container.end(), value, comp);
}

template <class Container, class Target>
inline typename Container::const_iterator lower_bound(const Container& container, const Target& value, IS_STL(Container))
{
    return std::lower_bound(container.begin(), container.end(), value);
}

template <class Container, class Target, class Compare>
inline typename Container::const_iterator lower_bound(const Container& container, const Target& value, Compare comp, IS_STL(Container))
{
    return std::lower_bound(container.begin(), container.end(), value, comp);
}

// upper_bound
template <class Type, int Size, class Target>
inline Type* upper_bound(Type (&ar)[Size], const Target& value, void* = 0)
{
    return std::upper_bound(ar, ar + Size, value);
}

template <class Type, int Size, class Target, class Compare>
inline Type* upper_bound(Type (&ar)[Size], const Target& value, Compare comp, void* = 0)
{
    return std::upper_bound(ar, ar + Size, value, comp);
}

template <class Container, class Target>
inline typename Container::iterator upper_bound(Container& container, const Target& value, IS_STL(Container))
{
    return std::upper_bound(container.begin(), container.end(), value);
}

template <class Container, class Target, class Compare>
inline typename Container::iterator upper_bound(Container& container, const Target& value, Compare comp, IS_STL(Container))
{
    return std::upper_bound(container.begin(), container.end(), value, comp);
}

template <class Container, class Target>
inline typename Container::const_iterator upper_bound(const Container& container, const Target& value, IS_STL(Container))
{
    return std::upper_bound(container.begin(), container.end(), value);
}

template <class Container, class Target, class Compare>
inline typename Container::const_iterator upper_bound(const Container& container, const Target& value, Compare comp, IS_STL(Container))
{
    return std::upper_bound(container.begin(), container.end(), value, comp);
}

// binary_search
template <class Type, int Size, class Target>
inline bool binary_search(Type (&ar)[Size], const Target& value, void* = 0)
{
    return std::binary_search(ar, ar + Size, value);
}

template <class Type, int Size, class Target, class Compare>
inline bool binary_search(Type (&ar)[Size], const Target& value, Compare comp, void* = 0)
{
    return std::binary_search(ar, ar + Size, value, comp);
}

template <class Container, class Target>
inline bool binary_search(const Container& container, const Target& value, IS_STL(Container))
{
    return std::binary_search(container.begin(), container.end(), value);
}

template <class Container, class Target, class Compare>
inline bool binary_search(const Container& container, const Target& value, Compare comp, IS_STL(Container))
{
    return std::binary_search(container.begin(), container.end(), value, comp);
}

// merge
template <class LType, int LSize, class RType, int RSize, class OutputIterator>
inline OutputIterator merge(LType (&lhs)[LSize], RType (&rhs)[RSize], OutputIterator result, void* = 0)
{
    return std::merge(lhs, lhs + LSize, rhs, rhs + RSize, result);
}

template <class LType, int LSize, class RType, int RSize, class OutputIterator, class Compare>
inline OutputIterator merge(LType (&lhs)[LSize], RType (&rhs)[RSize], OutputIterator result, Compare comp, void* = 0)
{
    return std::merge(lhs, lhs + LSize, rhs, rhs + RSize, result, comp);
}

template <class LContainer, class RContainer, class OutputIterator>
inline OutputIterator merge(const LContainer& lhs, const RContainer& rhs, OutputIterator result, IS_STL(LContainer))
{
    return std::merge(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), result);
}

template <class LContainer, class RContainer, class OutputIterator, class Compare>
inline OutputIterator merge(const LContainer& lhs, const RContainer& rhs, OutputIterator result, Compare comp, IS_STL(LContainer))
{
    return std::merge(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), result, comp);
}

// includes
template <class LType, int LSize, class RType, int RSize>
inline bool includes(LType (&lhs)[LSize], RType (&rhs)[RSize], void* = 0)
{
    return std::includes(lhs, lhs + LSize, rhs, rhs + RSize);
}

template <class LType, int LSize, class RType, int RSize, class Compare>
inline bool includes(LType (&lhs)[LSize], RType (&rhs)[RSize], Compare comp, void* = 0)
{
    return std::includes(lhs, lhs + LSize, rhs, rhs + RSize, comp);
}

template <class LContainer, class RContainer>
inline bool includes(const LContainer& lhs, const RContainer& rhs, IS_STL(LContainer))
{
    return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}

template <class LContainer, class RContainer, class Compare>
inline bool includes(const LContainer& lhs, const RContainer& rhs, Compare comp, IS_STL(LContainer))
{
    return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), comp);
}

// set_union
template <class LType, int LSize, class RType, int RSize, class OutputIterator>
inline OutputIterator set_union(LType (&lhs)[LSize], RType (&rhs)[RSize], OutputIterator result, void* = 0)
{
    return std::set_union(lhs, lhs + LSize, rhs, rhs + RSize, result);
}

template <class LType, int LSize, class RType, int RSize, class OutputIterator, class Compare>
inline OutputIterator set_union(LType (&lhs)[LSize], RType (&rhs)[RSize], OutputIterator result, Compare comp, void* = 0)
{
    return std::set_union(lhs, lhs + LSize, rhs, rhs + RSize, result, comp);
}

template <class LContainer, class RContainer, class OutputIterator>
inline OutputIterator set_union(const LContainer& lhs, const RContainer& rhs, OutputIterator result, IS_STL(LContainer))
{
    return std::set_union(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), result);
}

template <class LContainer, class RContainer, class OutputIterator, class Compare>
inline OutputIterator set_union(const LContainer& lhs, const RContainer& rhs, OutputIterator result, Compare comp, IS_STL(LContainer))
{
    return std::set_union(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), result, comp);
}

// set_intersection
template <class LType, int LSize, class RType, int RSize, class OutputIterator>
inline OutputIterator set_intersection(LType (&lhs)[LSize], RType (&rhs)[RSize], OutputIterator result, void* = 0)
{
    return std::set_intersection(lhs, lhs + LSize, rhs, rhs + RSize, result);
}

template <class LType, int LSize, class RType, int RSize, class OutputIterator, class Compare>
inline OutputIterator set_intersection(LType (&lhs)[LSize], RType (&rhs)[RSize], OutputIterator result, Compare comp, void* = 0)
{
    return std::set_intersection(lhs, lhs + LSize, rhs, rhs + RSize, result, comp);
}

template <class LContainer, class RContainer, class OutputIterator>
inline OutputIterator set_intersection(const LContainer& lhs, const RContainer& rhs, OutputIterator result, IS_STL(LContainer))
{
    return std::set_intersection(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), result);
}

template <class LContainer, class RContainer, class OutputIterator, class Compare>
inline OutputIterator set_intersection(const LContainer& lhs, const RContainer& rhs, OutputIterator result, Compare comp, IS_STL(LContainer))
{
    return std::set_intersection(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), result, comp);
}

// set_difference
template <class LType, int LSize, class RType, int RSize, class OutputIterator>
inline OutputIterator set_difference(LType (&lhs)[LSize], RType (&rhs)[RSize], OutputIterator result, void* = 0)
{
    return std::set_difference(lhs, lhs + LSize, rhs, rhs + RSize, result);
}

template <class LType, int LSize, class RType, int RSize, class OutputIterator, class Compare>
inline OutputIterator set_difference(LType (&lhs)[LSize], RType (&rhs)[RSize], OutputIterator result, Compare comp, void* = 0)
{
    return std::set_difference(lhs, lhs + LSize, rhs, rhs + RSize, result, comp);
}

template <class LContainer, class RContainer, class OutputIterator>
inline OutputIterator set_difference(const LContainer& lhs, const RContainer& rhs, OutputIterator result, IS_STL(LContainer))
{
    return std::set_difference(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), result);
}

template <class LContainer, class RContainer, class OutputIterator, class Compare>
inline OutputIterator set_difference(const LContainer& lhs, const RContainer& rhs, OutputIterator result, Compare comp, IS_STL(LContainer))
{
    return std::set_difference(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), result, comp);
}

// set_symmetric_difference
template <class LType, int LSize, class RType, int RSize, class OutputIterator>
inline OutputIterator set_symmetric_difference(LType (&lhs)[LSize], RType (&rhs)[RSize], OutputIterator result, void* = 0)
{
    return std::set_symmetric_difference(lhs, lhs + LSize, rhs, rhs + RSize, result);
}

template <class LType, int LSize, class RType, int RSize, class OutputIterator, class Compare>
inline OutputIterator set_symmetric_difference(LType (&lhs)[LSize], RType (&rhs)[RSize], OutputIterator result, Compare comp, void* = 0)
{
    return std::set_symmetric_difference(lhs, lhs + LSize, rhs, rhs + RSize, result, comp);
}

template <class LContainer, class RContainer, class OutputIterator>
inline OutputIterator set_symmetric_difference(const LContainer& lhs, const RContainer& rhs, OutputIterator result, IS_STL(LContainer))
{
    return std::set_symmetric_difference(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), result);
}

template <class LContainer, class RContainer, class OutputIterator, class Compare>
inline OutputIterator set_symmetric_difference(const LContainer& lhs, const RContainer& rhs, OutputIterator result, Compare comp, IS_STL(LContainer))
{
    return std::set_symmetric_difference(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), result, comp);
}

// push_heap
template <class Type, int Size>
inline void push_heap(Type (&ar)[Size], void* = 0)
{
    std::push_heap(ar, ar + Size);
}

template <class Type, int Size, class Compare>
inline void push_heap(Type (&ar)[Size], Compare comp, void* = 0)
{
    std::push_heap(ar, ar + Size, comp);
}

template <class Container>
inline void push_heap(Container& container, IS_STL(Container))
{
    std::push_heap(container.begin(), container.end());
}

template <class Container, class Compare>
inline void push_heap(Container& container, Compare comp, IS_STL(Container))
{
    std::push_heap(container.begin(), container.end(), comp);
}

// pop_heap
template <class Type, int Size>
inline void pop_heap(Type (&ar)[Size], void* = 0)
{
    std::pop_heap(ar, ar + Size);
}

template <class Type, int Size, class Compare>
inline void pop_heap(Type (&ar)[Size], Compare comp, void* = 0)
{
    std::pop_heap(ar, ar + Size, comp);
}

template <class Container>
inline void pop_heap(Container& container, IS_STL(Container))
{
    std::pop_heap(container.begin(), container.end());
}

template <class Container, class Compare>
inline void pop_heap(Container& container, Compare comp, IS_STL(Container))
{
    std::pop_heap(container.begin(), container.end(), comp);
}

// make_heap
template <class Type, int Size>
inline void make_heap(Type (&ar)[Size], void* = 0)
{
    std::make_heap(ar, ar + Size);
}

template <class Type, int Size, class Compare>
inline void make_heap(Type (&ar)[Size], Compare comp, void* = 0)
{
    std::make_heap(ar, ar + Size, comp);
}

template <class Container>
inline void make_heap(Container& container, IS_STL(Container))
{
    std::make_heap(container.begin(), container.end());
}

template <class Container, class Compare>
inline void make_heap(Container& container, Compare comp, IS_STL(Container))
{
    std::make_heap(container.begin(), container.end(), comp);
}

// sort_heap
template <class Type, int Size>
inline void sort_heap(Type (&ar)[Size], void* = 0)
{
    std::sort_heap(ar, ar + Size);
}

template <class Type, int Size, class Compare>
inline void sort_heap(Type (&ar)[Size], Compare comp, void* = 0)
{
    std::sort_heap(ar, ar + Size, comp);
}

template <class Container>
inline void sort_heap(Container& container, IS_STL(Container))
{
    std::sort_heap(container.begin(), container.end());
}

template <class Container, class Compare>
inline void sort_heap(Container& container, Compare comp, IS_STL(Container))
{
    std::sort_heap(container.begin(), container.end(), comp);
}

// min_element
template <class Type, int Size>
inline Type* min_element(Type (&ar)[Size], void* = 0)
{
    return std::min_element(ar, ar + Size);
}

template <class Type, int Size, class Compare>
inline Type* min_element(Type (&ar)[Size], Compare comp, void* = 0)
{
    return std::min_element(ar, ar + Size, comp);
}

template <class Container>
inline typename Container::iterator min_element(Container& container, IS_STL(Container))
{
    return std::min_element(container.begin(), container.end());
}

template <class Container, class Compare>
inline typename Container::iterator min_element(Container& container, Compare comp, IS_STL(Container))
{
    return std::min_element(container.begin(), container.end(), comp);
}

template <class Container>
inline typename Container::const_iterator min_element(const Container& container, IS_STL(Container))
{
    return std::min_element(container.begin(), container.end());
}

template <class Container, class Compare>
inline typename Container::const_iterator min_element(const Container& container, Compare comp, IS_STL(Container))
{
    return std::min_element(container.begin(), container.end(), comp);
}

// max_element
template <class Type, int Size>
inline Type* max_element(Type (&ar)[Size], void* = 0)
{
    return std::max_element(ar, ar + Size);
}

template <class Type, int Size, class Compare>
inline Type* max_element(Type (&ar)[Size], Compare comp, void* = 0)
{
    return std::max_element(ar, ar + Size, comp);
}

template <class Container>
inline typename Container::iterator max_element(Container& container, IS_STL(Container))
{
    return std::max_element(container.begin(), container.end());
}

template <class Container, class Compare>
inline typename Container::iterator max_element(Container& container, Compare comp, IS_STL(Container))
{
    return std::max_element(container.begin(), container.end(), comp);
}

template <class Container>
inline typename Container::const_iterator max_element(const Container& container, IS_STL(Container))
{
    return std::max_element(container.begin(), container.end());
}

template <class Container, class Compare>
inline typename Container::const_iterator max_element(const Container& container, Compare comp, IS_STL(Container))
{
    return std::max_element(container.begin(), container.end(), comp);
}

// lexicographical_compare
template <class LType, int LSize, class RType, int RSize>
inline bool lexicographical_compare(LType (&lhs)[LSize], RType (&rhs)[RSize], void* = 0)
{
    return std::lexicographical_compare(lhs, lhs + LSize, rhs, rhs + RSize);
}

template <class LType, int LSize, class RType, int RSize, class Compare>
inline bool lexicographical_compare(LType (&lhs)[LSize], RType (&rhs)[RSize], Compare comp, void* = 0)
{
    return std::lexicographical_compare(lhs, lhs + LSize, rhs, rhs + RSize, comp);
}

template <class LContainer, class RContainer>
inline bool lexicographical_compare(const LContainer& lhs, const RContainer& rhs, IS_STL(LContainer))
{
    return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}

template <class LContainer, class RContainer, class Compare>
inline bool lexicographical_compare(const LContainer& lhs, const RContainer& rhs, Compare comp, IS_STL(LContainer))
{
    return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), comp);
}

// next_permutation
template <class Type, int Size>
inline bool next_permutation(Type (&ar)[Size], void* = 0)
{
    return std::next_permutation(ar, ar + Size);
}

template <class Type, int Size, class Compare>
inline bool next_permutation(Type (&ar)[Size], Compare comp, void* = 0)
{
    return std::next_permutation(ar, ar + Size, comp);
}

template <class Container>
inline bool next_permutation(Container& container, IS_STL(Container))
{
    return std::next_permutation(container.begin(), container.end());
}

template <class Container, class Compare>
inline bool next_permutation(Container& container, Compare comp, IS_STL(Container))
{
    return std::next_permutation(container.begin(), container.end(), comp);
}

// prev_permutation
template <class Type, int Size>
inline bool prev_permutation(Type (&ar)[Size], void* = 0)
{
    return std::prev_permutation(ar, ar + Size);
}

template <class Type, int Size, class Compare>
inline bool prev_permutation(Type (&ar)[Size], Compare comp, void* = 0)
{
    return std::prev_permutation(ar, ar + Size, comp);
}

template <class Container>
inline bool prev_permutation(Container& container, IS_STL(Container))
{
    return std::prev_permutation(container.begin(), container.end());
}

template <class Container, class Compare>
inline bool prev_permutation(Container& container, Compare comp, IS_STL(Container))
{
    return std::prev_permutation(container.begin(), container.end(), comp);
}


#endif // SHAND_SUPPORT_SFINAE


} // namespace shand

#undef SHAND_SUPPORT_SFINAE
#undef IS_STL