optional_front

Default values for range access adaptors?


Rangeの先頭要素にアクセスするアダプターで、アクセスできなかった場合にデフォルト値を指定させてほしい、というリクエストがありました。
Ovenから移植し、Boost.Rangeの拡張として開発しているOvenToBoostのfrontアクセッサーは参照を返すので、値(not 参照)であるデフォルト値を許可するのは難しいです。なので、optionalを返すoptional_frontを実装しました。

#include <iostream>
#include <vector>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/access/front.hpp>

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

int main()
{
    using namespace boost::adaptors;
    using namespace boost::range::access;

    std::vector<int> v = boost::assign::list_of(1)(2)(3);

    if (boost::optional<int&> x = v | filtered(is_even) | optional_front) {
        std::cout << x.get() << std::endl;
    }
    else {
        std::cout << "not found" << std::endl;
    }
}
2

同様に、最後尾要素にアクセスするoptional_back、ランダムアクセスするoptional_atも実装してあります。

Michel Morinさんから、他のアダプターとの一貫性のために、frontはsingle rangeを返すべきじゃないか、というフィードバックをもらいました。たしかに、optionalの代わりにrangeを返す方法もありだと思います。

for (T x : r | front) {
    std::cout << x << std::endl;
}

この設計にすれば、要素にアクセスできたらその要素がfor文で1回だけ取得され、アクセスできなかったら空のrangeが返されます。
設計的にはこの選択肢もありだと思いますが、既存の設計のfrontoptional_rangeも便利だと思うので、これらに加えてfront_rangeを追加しようと考えています。


なお、OvenToBoostプロジェクトは間もなくBoost.Rangeにマージされる予定になっています。
Time to merge Oven-to-Boost Extensions?
今月中にはマージしてくれるそうです。優先度の高いものから順次入れていくそうなので、私の方も引き続き追加機能の実装を進めていくつもりです。