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

非標準のcopy_ifをremove_copy_ifで代用

C++

C++03 の標準ライブラリでは copy_if アルゴリズムは用意されていませんが、 remove_copy_if で代用することはできます


remove_copy_if は、 copy_if の反対の動作である「述語の条件を満たさない要素をコピー」を行うので
remove_if の引数である述語に not1 を適用することで結果を逆にしてあげればいいのです

#include <iterator>
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

struct is_even : public unary_function<int, bool> {
    bool operator()(int value) const
    {
        return value % 2 == 0;
    }
};

int main()
{
    vector<int> v;

    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);

    // 偶数のみ出力する
    remove_copy_if(v.begin(), v.end(), ostream_iterator<int>(cout, "\n"), not1(is_even()));
        // 2, 4
}


ただし、 not1 には unary_function を継承した型しか渡せないので、関数ポインタを渡すことはできません

bool is_even(int value)
{
    return value % 2 == 0;
}

...

remove_copy_if(v.begin(), v.end(), ostream_iterator<int>(cout, "\n"), not1(is_even)); // エラー!


それに、 remove_copy_if + not1 で copy_if の代用をするのはまぎらわしいので、やはり copy_if は標準で提供されるべきです

template <class InputIterator, class OutputIterator, class Predicate>
inline OutputIterator copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred)
{
    while (first != last) {
        if (pred(*first))
            *result++ = *first;
        ++first;
    }
    return result;
}

という動機で、 C++0x に copy_if が実装されるそうです



『Effective STL』の内容をすっかり忘れてました。