predicateの記述法

c++の理解が浅すぎるので迂闊なことは書けないですが自分へのメモ。

std::sortやstd::transformを使っているとpredicateを指定する状況が自然に生まれてきます。

predicateは関数オブジェクトで表すことができます。関数オブジェクトは()をオーバーロードしたクラスで表すことができます。途中で関数ポインタとの違いが分からなくなって
[*1]を参考にしました。インライン化に関しての理解が浅いので後で[*2]を読みます。

ところでlambda式が評価されるとclosure objectになります[*3]。closure objectは一種の関数オブジェクトになります。よってpredicateはlabmda式で表すことができます。

サンプルコード

int main() {
    auto compare = [](const std::complex<float> &a, const std::complex<float> &b) -> bool {
        if(abs(a) == abs(b)) {
            if(a.real() == b.real()) return a.imag() > b.imag();
            return a.real() > b.real();
        } else {
            return abs(a) > abs(b);
        }
    };

    std::vector<std::complex<float>> seq;
    seq.push_back(std::complex<float>(0.5f, 1.0f));
    seq.push_back(std::complex<float>(0.5f, 0.3f));
    seq.push_back(std::complex<float>(4.2f, -1.0f));
    seq.push_back(std::complex<float>(0.0f, -2.0f));
    seq.push_back(std::complex<float>(2.0f, 0.0f));
    seq.push_back(std::complex<float>(-2.0f, 0.0f));

    std::priority_queue<std::complex<float>, std::vector<std::complex<float>>, decltype(compare)> queue(compare);
    for(auto element : seq) {
        queue.push(element);
    }
    
    std::sort(seq.begin(), seq.end(), compare);

    std::cout << "std::sort" << endl;
    for(auto element : seq) {
        std::cout << element.real() << ',' << element.imag() << std::endl; 
    }

    std::cout << "std::priority_queue" << endl;
    for(; !queue.empty(); queue.pop()) {
        auto element = queue.top();
        std::cout << element.real() << ',' << element.imag() << std::endl; 
    }
}

出力

std::sort
4.2,-1
2,0
0,-2
-2,0
0.5,1
0.5,0.3
std::priority_queue
0.5,0.3
0.5,1
-2,0
0,-2
2,0
4.2,-1

参考文献