std::map で remove_if をする

いろいろと考えていたんですが Boost.Range の filter でそれっぽく処理することが出来ました。

[ソース]

#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/bind.hpp>
#include <map>
#include <string>
#include <iostream>

bool
over_three(std::pair<int, std::string> const& pair){
    return pair.first >= 3;
}

void
disp(std::pair<int, std::string> const& pair){
    std::cout << pair.first << ":" << pair.second << std::endl;
}

int
main(){
    using boost::adaptors::filter;

    std::map<int, std::string> data;
    data[0] = "zero";
    data[1] = "one";
    data[2] = "two";
    data[3] = "three";
    data[4] = "four";
    data[5] = "five";
    
    // ! を使いたかったので、boost::bind でラップ
    BOOST_AUTO(result_range, filter(data, !boost::bind(&over_three, _1)) );
    std::map<int, std::string> result(result_range.begin(), result_range.end());

    std::cout << ">result" << std::endl;
    boost::for_each(result, disp);
    std::cout << ">data" << std::endl;
    boost::for_each(data, disp);
    
    return 0;
}

[出力]

>result
0:zero
1:one
2:two
>data
0:zero
1:one
2:two
3:three
4:four
5:five

んーこれでいいかしら。
range から map にコピーするのがちょっとめんどくさいですね…。
もっとスマートなやり方はあるかな。

[boost]

  • ver 1.47.0

Boost.Phoenix で、std::map の remove_if を書いてみた

Boost.Range を思いつく前に書いたボツネタ。
iterator を回して直接、値を削除しています。
Boost.Phoenix に first と second が欲しいですね。

[ソース]

#include <boost/phoenix.hpp>
#include <boost/typeof/typeof.hpp>
#include <map>
#include <string>
#include <iostream>

template<typename T>
typename T::first_type
first_impl(T& pair){
    return pair.first;
}

template<typename T>
typename T::second_type
second_impl(T& pair){
    return pair.second;
}

BOOST_PHOENIX_ADAPT_FUNCTION(
    typename boost::remove_reference<A0>::type::first_type,
    first,
    first_impl,
    1
)

BOOST_PHOENIX_ADAPT_FUNCTION(
    typename boost::remove_reference<A0>::type::second_type,
    second,
    second_impl,
    1
)

int
main(){
    namespace phx = boost::phoenix;
    using phx::arg_names::arg1;
    using phx::arg_names::arg2;
    using phx::local_names::_b;

    std::map<int, std::string> data;
    data[0] = "zero";
    data[1] = "one";
    data[2] = "two";
    data[3] = "three";
    data[4] = "four";
    data[5] = "five";
    
    boost_auto(remove_if,
        phx::let(_b = phx::begin(arg1))[
            phx::while_(_b != phx::end(arg1))[
                phx::if_(phx::bind(arg2, *_b))[
                    phx::erase(arg1, _b++)
                ]
                .else_[
                    ++_b
                ]
            ]
        ]
    );
    remove_if(data, first(arg1) >= 3);
    
    std::for_each(data.begin(), data.end(),
        std::cout << first(arg1) << ":" << second(arg1) << std::endl);

    return 0;
}

[出力]

0:zero
1:one
2:two

[boost]

  • ver 1.47.0