アダプトされたイテレータの元の値を得る

Range adaptors and compatibility with non-adapted iterators


先日、Boost MLであった話。

map<int, string> m;

auto it = find_if(m | map_values, pred);
if (it != m.end()) {
}

Rangeアダプタ適用結果を用いてイテレータを得た場合、そのイテレータイテレータアダプタに変換された型となるため、このような書き方をすると、if文のところで、「itの型とm.end()の型が合わない」というコンパイルエラーになってしまう問題があります。


この解決策として私は、イテレータを直接使用せずにoptionalを使う書き方を推奨したのですが、他の方はbase()関数を使用して元のイテレータを取得する方法を提示していました。

#include <iostream>
#include <map>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/algorithm/find_if.hpp>

bool is_alice(const std::string& name)
{
    return name == "Alice";
}

int main()
{
    std::map<int, std::string> m = {{3, "Alice"}, {1,"Bob"}, {4, "Carol"}};

    auto it = boost::find_if(m | boost::adaptors::map_values, is_alice);
    if (it.base() != m.end()) {
        std::cout << "found:" << *it << std::endl;
    }
    else {
        std::cout << "not found" << std::endl;
    }
}
found:Alice

こんなことができるとは知らなかった。