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

SFINAE版STLアルゴリズム(たぶん最終版)

いままでは各アルゴリズム毎に配列版とコンテナ版を作っていましたが
今回はBoost.Rangeようにbeginとendの汎用版を作って
配列とコンテナを同じように扱えるようにしました



サンプル(使い方は今までと同じ)

#include <iostream>
#include <vector>
#include <shand/algorithm.hpp>

using namespace std;
using namespace shand;

void disp(int value) { cout << value << endl; }

int main()
{
    vector<int> v; // コンテナ
    int ar[3];     // 配列

    // 並び替え
    sort(v);
    sort(ar);

    // 全要素表示
    copy(v,  ostream_iterator<int>(cout, "\n"));
    copy(ar, ostream_iterator<int>(cout, "\n"));

    for_each(v,  disp);
    for_each(ar, disp);

    // 検索
    vector<int>::iterator it = find(v,  1);
    int*                  p  = find(ar, 1);

    // 汎用化されたbegin/endを使ってみる
    sort(begin(v),  end(v));
    sort(begin(ar), end(ar));

    // 使わないだろうけどstd::pairも渡せる
    sort(make_pair(begin(v),  end(v)));
    sort(make_pair(begin(ar), end(ar)));

    return 0;
}

ソースは以下

#ifndef SHAND_ALGORITHM_INCLUDE
#define SHAND_ALGORITHM_INCLUDE

#include <algorithm>
#include <utility>

namespace shand {

#ifdef SHAND_SUPPORT_SFINAE

// 反復子の型取得
template <class Container>
struct range_iterator {
    typedef typename Container::iterator type;
};

template <class Container>
struct range_iterator< const Container > {
    typedef typename Container::const_iterator type;
};

template <class Type, int Size>
struct range_iterator< Type[Size] > {
    typedef Type* type;
};

template <class Type, int Size>
struct range_iterator< const Type[Size] > {
    typedef const Type* type;
};

template<>
struct range_iterator< char* >
{
    typedef char* type;
};

// 配列 - 先頭要素へのポインタ取得
template <class Type, int Size>
inline Type* begin(Type (&ar)[Size])
{
    return ar;
}

// 配列 - 最後尾要素へのポインタ取得
template <class Type, int Size>
inline Type* end(Type (&ar)[Size])
{
    return ar + Size;
}

// コンテナ - 先頭イテレータ取得
template <class Container>
inline typename Container::iterator begin(Container& c)
{
    return c.begin();
}

template <class Container>
inline typename Container::const_iterator begin(const Container& c)
{
    return c.begin();
}

// コンテナ - 最後尾イテレータ取得
template <class Container>
inline typename Container::iterator end(Container& c)
{
    return c.end();
}

template <class Container>
inline typename Container::const_iterator end(const Container& c)
{
    return c.end();
}

// std::pair
template <class Iterator>
inline Iterator begin(const std::pair<Iterator, Iterator>& p)
{
    return p.first;
}

template <class Iterator>
inline Iterator end(const std::pair<Iterator, Iterator>& p)
{
    return p.second;
}

#define SHAND_RANGE_ITERATOR    typename range_iterator<Container>::type
#define SHAND_RANGE_CITERATOR   typename range_iterator<const Container>::type

#endif // SHAND_SUPPORT_SFINAE


// SFINAE版STLアルゴリズム -----------------------------
#ifdef SHAND_SUPPORT_SFINAE

// for_each
template <class Container, class Pred>
inline Pred for_each(const Container& c, Pred pred)
{
    return std::for_each(begin(c), end(c), pred);
}

// find
template <class Container, class Target>
inline SHAND_RANGE_ITERATOR find(Container& c, const Target& value)
{
    return std::find(begin(c), end(c), value);
}

template <class Container, class Target>
inline SHAND_RANGE_CITERATOR find(const Container& c, const Target& value)
{
    return std::find(begin(c), end(c), value);
}

// find_if
template <class Container, class Pred>
inline SHAND_RANGE_ITERATOR find_if(Container& c, Pred pred)
{
    return std::find_if(begin(c), end(c), pred);
}

template <class Container, class Pred>
inline SHAND_RANGE_CITERATOR find_if(const Container& c, Pred pred)
{
    return std::find_if(begin(c), end(c), pred);
}

// find_first_of
template <class LContainer, class RContainer>
inline typename range_iterator<LContainer>::type find_first_of(LContainer &lhs, RContainer &rhs)
{
    return std::find_first_of(begin(lhs), end(lhs), begin(rhs), end(rhs));
}

template <class LContainer, class RContainer, class Pred>
inline typename range_iterator<LContainer>::type find_first_of(LContainer &lhs, RContainer &rhs, Pred pred)
{
    return std::find_first_of(begin(lhs), end(lhs), begin(rhs), end(rhs), pred);
}

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

template <class LContainer, class RContainer, class Pred>
inline typename range_iterator<const LContainer>::type find_first_of(const LContainer& lhs, const RContainer& rhs, Pred pred)
{
    return std::find_first_of(begin(lhs), end(lhs), begin(rhs), end(rhs), pred);
}

// find_end
template <class LContainer, class RContainer>
inline typename range_iterator<LContainer>::type find_end(LContainer &lhs, RContainer &rhs)
{
    return std::find_end(begin(lhs), end(lhs), begin(rhs), end(rhs));
}

template <class LContainer, class RContainer, class Pred>
inline typename range_iterator<LContainer>::type find_end(LContainer &lhs, RContainer &rhs, Pred pred)
{
    return std::find_end(begin(lhs), end(lhs), begin(rhs), end(rhs), pred);
}

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

template <class LContainer, class RContainer, class Pred>
inline typename range_iterator<const LContainer>::type find_end(const LContainer& lhs, const RContainer& rhs, Pred pred)
{
    return std::find_end(begin(lhs), end(lhs), begin(rhs), end(rhs), pred);
}

// adjacent_find
template <class Container>
inline SHAND_RANGE_ITERATOR adjacent_find(Container& c)
{
    return std::adjacent_find(begin(c), end(c));
}

template <class Container>
inline SHAND_RANGE_CITERATOR adjacent_find(const Container& c)
{
    return std::adjacent_find(begin(c), end(c));
}

template <class Container, class Pred>
inline SHAND_RANGE_ITERATOR adjacent_find(Container& c, Pred pred)
{
    return std::adjacent_find(begin(c), end(c), pred);
}

template <class Container, class Pred>
inline SHAND_RANGE_CITERATOR adjacent_find(const Container& c, Pred pred)
{
    return std::adjacent_find(begin(c), end(c), pred);
}

// count
template <class Container, class Target>
inline size_t count(const Container& c, const Target& value)
{
    return std::count(begin(c), end(c), value);
}

// count_if
template <class Container, class Pred>
inline typename size_t count_if(const Container& c, Pred pred)
{
    return std::count_if(begin(c), end(c), pred);
}

// mismatch
template <class Container, class InputIterator>
inline std::pair<SHAND_RANGE_ITERATOR, InputIterator> mismatch(Container& c, InputIterator first)
{
    return std::mismatch(begin(c), end(c), first);
}

template <class Container, class InputIterator, class Pred>
inline std::pair<SHAND_RANGE_ITERATOR, InputIterator> mismatch(Container& c, InputIterator first, Pred pred)
{
    return std::mismatch(begin(c), end(c), first, pred);
}

template <class Container, class InputIterator>
inline std::pair<SHAND_RANGE_CITERATOR, InputIterator> mismatch(const Container& c, InputIterator first)
{
    return std::mismatch(begin(c), end(c), first);
}

template <class Container, class InputIterator, class Pred>
inline std::pair<SHAND_RANGE_CITERATOR, InputIterator> mismatch(const Container& c, InputIterator first, Pred pred)
{
    return std::mismatch(begin(c), end(c), first, pred);
}

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

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

// search
template <class LContainer, class RContainer>
inline typename range_iterator<LContainer>::type search(LContainer& lhs, RContainer& rhs)
{
    return std::search(begin(lhs), end(lhs), begin(rhs), end(rhs));
}

template <class LContainer, class RContainer, class BynaryPred>
inline typename range_iterator<LContainer>::type search(LContainer& lhs, RContainer& rhs, BynaryPred pred)
{
    return std::search(begin(lhs), end(lhs), begin(rhs), end(rhs), pred);
}

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

template <class LContainer, class RContainer, class BynaryPred>
inline typename range_iterator<const LContainer>::type search(const LContainer& lhs, const RContainer& rhs, BynaryPred pred)
{
    return std::search(begin(lhs), end(lhs), begin(rhs), end(rhs), pred);
}

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

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

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

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

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

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

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

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

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

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

// remove
template <class Container, class Target>
inline SHAND_RANGE_ITERATOR remove(Container& c, const Target& value)
{
    return std::remove(begin(c), end(c), value);
}

// remove_if
template <class Container, class Pred>
inline SHAND_RANGE_ITERATOR remove_if(Container& c, Pred pred)
{
    return std::remove_if(begin(c), end(c), pred);
}

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

// remove_copy_if
template <class Container, class OutputIterator, class Pred>
inline OutputIterator remove_copy_if(const Container& c, OutputIterator result, Pred pred)
{
    return std::remove_copy_if(begin(c), end(c), result, pred);
}

// unique
template <class Container>
inline SHAND_RANGE_ITERATOR unique(Container& c)
{
    return std::unique(begin(c), end(c));
}

template <class Container, class BynaryPred>
inline SHAND_RANGE_ITERATOR unique(Container& c, BynaryPred pred)
{
    return std::unique(begin(c), end(c), pred);
}

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

template <class Container, class OutputIterator, class BynaryPred>
inline OutputIterator unique_copy(const Container& c, OutputIterator result, BynaryPred pred)
{
    return std::unique_copy(begin(c), end(c), result, pred);
}

// reverse
template <class Container>
inline void reverse(Container& c)
{
    std::reverse(begin(c), end(c));
}

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

// random_shuffle
template <class Container>
inline void random_shuffle(Container& c)
{
    std::random_shuffle(begin(c), end(c));
}

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

// partition
template <class Container, class Pred>
inline SHAND_RANGE_ITERATOR partition(Container& c, Pred pred)
{
    return std::partition(begin(c), end(c), pred);
}

// stable_partition
template <class Container, class Pred>
inline SHAND_RANGE_ITERATOR stable_partition(Container& c, Pred pred)
{
    return std::stable_partition(begin(c), end(c), pred);
}

// sort
template <class Container>
inline void sort(Container& c)
{
    std::sort(begin(c), end(c));
}

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

// stable_sort
template <class Container>
inline void stable_sort(Container& c)
{
    std::stable_sort(begin(c), end(c));
}

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

// lower_bound
template <class Container, class Target>
inline SHAND_RANGE_ITERATOR lower_bound(Container& c, const Target& value)
{
    return std::lower_bound(begin(c), end(c), value);
}

template <class Container, class Target, class Compare>
inline SHAND_RANGE_ITERATOR lower_bound(Container& c, const Target& value, Compare comp)
{
    return std::lower_bound(begin(c), end(c), value, comp);
}

template <class Container, class Target>
inline SHAND_RANGE_CITERATOR lower_bound(const Container& c, const Target& value)
{
    return std::lower_bound(begin(c), end(c), value);
}

template <class Container, class Target, class Compare>
inline SHAND_RANGE_CITERATOR lower_bound(const Container& c, const Target& value, Compare comp)
{
    return std::lower_bound(begin(c), end(c), value, comp);
}

// upper_bound
template <class Container, class Target>
inline SHAND_RANGE_ITERATOR upper_bound(Container& c, const Target& value)
{
    return std::upper_bound(begin(c), end(c), value);
}

template <class Container, class Target, class Compare>
inline SHAND_RANGE_ITERATOR upper_bound(Container& c, const Target& value, Compare comp)
{
    return std::upper_bound(begin(c), end(c), value, comp);
}

template <class Container, class Target>
inline SHAND_RANGE_CITERATOR upper_bound(const Container& c, const Target& value)
{
    return std::upper_bound(begin(c), end(c), value);
}

template <class Container, class Target, class Compare>
inline SHAND_RANGE_CITERATOR upper_bound(const Container& c, const Target& value, Compare comp)
{
    return std::upper_bound(begin(c), end(c), value, comp);
}

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

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

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

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

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

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

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

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

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

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

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

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

// set_symmetric_difference
template <class LContainer, class RContainer, class OutputIterator>
inline OutputIterator set_symmetric_difference(const LContainer& lhs, const RContainer& rhs, OutputIterator result)
{
    return std::set_symmetric_difference(begin(lhs), end(lhs), begin(rhs), end(rhs), 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)
{
    return std::set_symmetric_difference(begin(lhs), end(lhs), begin(rhs), end(rhs), result, comp);
}

// push_heap
template <class Container>
inline void push_heap(Container& c)
{
    std::push_heap(begin(c), end(c));
}

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

// pop_heap
template <class Container>
inline void pop_heap(Container& c)
{
    std::pop_heap(begin(c), end(c));
}

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

// make_heap
template <class Container>
inline void make_heap(Container& c)
{
    std::make_heap(begin(c), end(c));
}

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

// sort_heap
template <class Container>
inline void sort_heap(Container& c)
{
    std::sort_heap(begin(c), end(c));
}

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

// min_element
template <class Container>
inline SHAND_RANGE_ITERATOR min_element(Container& c)
{
    return std::min_element(begin(c), end(c));
}

template <class Container, class Compare>
inline SHAND_RANGE_ITERATOR min_element(Container& c, Compare comp)
{
    return std::min_element(begin(c), end(c), comp);
}

template <class Container>
inline SHAND_RANGE_CITERATOR min_element(const Container& c)
{
    return std::min_element(begin(c), end(c));
}

template <class Container, class Compare>
inline SHAND_RANGE_CITERATOR min_element(const Container& c, Compare comp)
{
    return std::min_element(begin(c), end(c), comp);
}

// max_element
template <class Container>
inline SHAND_RANGE_ITERATOR max_element(Container& c)
{
    return std::max_element(begin(c), end(c));
}

template <class Container, class Compare>
inline SHAND_RANGE_ITERATOR max_element(Container& c, Compare comp)
{
    return std::max_element(begin(c), end(c), comp);
}

template <class Container>
inline SHAND_RANGE_CITERATOR max_element(const Container& c)
{
    return std::max_element(begin(c), end(c));
}

template <class Container, class Compare>
inline SHAND_RANGE_CITERATOR max_element(const Container& c, Compare comp)
{
    return std::max_element(begin(c), end(c), comp);
}

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

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

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

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

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

template <class Container, class Compare>
inline bool prev_permutation(Container& c, Compare comp)
{
    return std::prev_permutation(begin(c), end(c), comp);
}
#endif SHAND_SUPPORT_SFINAE

} // namespace shand


// delete macro
#undef SHAND_RANGE_ITERATOR
#undef SHAND_RANGE_CITERATOR
#undef SHAND_SUPPORT_SFINAE


#endif // SHAND_ALGORITHM_INCLUDE


ライブラリまとめ