叙述関数(プレディケート)

http://www.geocities.jp/ky_webid/cpp/library/017.html

叙述とな。名前からはどんなものなのか想像もつきません。

さぞかし難しい話なんだろうなと思いきや、何のことはありませんでした。

叙述関数とは以下のような関数のことを指します。

#include <iostream>
using namespace std;

bool equal (int num) {
    return 3 == num;
}

int main () {
    
    cout << equal(1) << endl;
    cout << equal(3) << endl;
    
    return 0;
}
$ main
0
1

え、何?たったこれだけ?

そう、たったこれだけです。

叙述関数とは単なるbool型の戻り値を持つ関数のことを指します。

さてこれを何処で使うのかということですが、algorithmヘッダに存在するテンプレート関数の中で、叙述関数を受け取って処理する関数がいくつかあるのです。

ひとつ例を見てみましょう。

count_if関数です。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

bool equal (int num) {
    return 3 == num;
}

int main () {
    vector<int> data;
    
    data.push_back(1);
    data.push_back(2);
    data.push_back(3);
    data.push_back(3);
    
    int res = static_cast<int>( count_if(data.begin(),data.end(),equal) );
    
    cout << "3は" << res << "個ありました" << endl;
    
    return 0;
}
$ main
3は2個ありました

count_if関数は与えられた要素の中で、第三引数に渡される関数のポインタの条件に合う要素の数を返します。

今回はequal関数を渡したので、値が3の物がいくつ含まれているかを取得することが出来ました。

しかし、値が4の場合や5の場合等、比較する値を別の物にしたければ単なる関数だと無理があります。

そこで前に学習した関数オブジェクトを利用します。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

class CEqual {
private:
    int m_num;
public:
    CEqual(int num) : m_num(num) {}
    
    int Get() const {
        return m_num;
    }
    
    // 関数オブジェクト
    bool operator()(int num) const {
        return m_num == num;
    }
};

int main () {
    vector<int> data;
    CEqual equal(2);
    
    data.push_back(1);
    data.push_back(2);
    data.push_back(3);
    data.push_back(3);
    
    int res = static_cast<int>( count_if(data.begin(),data.end(),equal) );
    
    cout << equal.Get() << "は" << res << "個ありました" << endl;
    
    return 0;
}
$ main
2は1個ありました

このように関数オブジェクトの場合は、単なる関数の場合と違ってオブジェクトなのでメンバ変数で値を保持できるのが強みです。

algorithmヘッダには他にも〜_if系の関数がいくつか用意されているのでそれらは追々学習していきたいと思います。