Tech Blog

勉強したことをまとめます。

boost/range/adaptorサンプル集

はじめに

 ずいぶん昔にGooglebloggerに作ったboost/range/adaptorのサンプル集が、bloggerの仕様が変わって表示されなくなりました。こちらに転載します。

サンプル集

#include <boost/range/irange.hpp>
#include <boost/range/adaptor/adjacent_filtered.hpp>
#include <boost/range/adaptor/copied.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/indexed.hpp>
#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/adaptor/replaced.hpp>
#include <boost/range/adaptor/replaced_if.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <boost/range/adaptor/strided.hpp>
#include <boost/range/adaptor/tokenized.hpp>
#include <boost/range/adaptor/type_erased.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/adaptor/uniqued.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/combine.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <iostream>
#include <boost/regex.h>

void test_adjacent_filtered()
{
    const auto range = {1, 1, 1, 2, 2, 3, 4, 5, 5};
    const auto result = range | boost::adaptors::adjacent_filtered([](auto a, auto b){ return a != b; });
    boost::copy(result, std::ostream_iterator<int>(std::cout, ", "));
    std::cout << std::endl;
}

void test_copied()
{
    const auto range = std::vector<int>{10, 20, 30, 40, 50};
    const auto result = range | boost::adaptors::copied(1, 3);
    boost::copy(result, std::ostream_iterator<int>(std::cout, ", "));
    std::cout << std::endl;
}

void test_filtered()
{
    const auto range = boost::irange(0, 10);
    const auto result = range | boost::adaptors::filtered([](auto v){ return v % 2 == 0; });
    boost::copy(result, std::ostream_iterator<int>(std::cout, ", "));
    std::cout << std::endl;
}

void test_indexed()
{
    const auto range = boost::irange(100, 110);
    for ( const auto& v : range | boost::adaptors::indexed(3) ) {
        std::cout << v.index() << " --- " << v.value() << std::endl;
    }
}

void test_indirected()
{
    const auto range = std::vector<std::shared_ptr<int>> {
        std::make_shared<int>(10),
        std::make_shared<int>(20),
        std::make_shared<int>(30),
    };
    boost::copy(range | boost::adaptors::indirected, std::ostream_iterator<int>(std::cout, ", "));
    std::cout << std::endl;
    
}

void test_map()
{
    const auto range = std::map<int, std::string> {
        {1, "tokyo"},
        {2, "osaka"},
        {3, "nagoya"},
    };
    
    boost::copy(range | boost::adaptors::map_keys, std::ostream_iterator<int>(std::cout, ", "));
    std::cout << std::endl;
    
    boost::copy(range | boost::adaptors::map_values, std::ostream_iterator<std::string>(std::cout, ", "));
    std::cout << std::endl;
}

void test_replaced()
{
    const auto range = std::string{"tokyo"};
    boost::copy(range | boost::adaptors::replaced('o', 'O'), std::ostream_iterator<char>(std::cout, ""));
    std::cout << std::endl;
}

void test_replaced_if()
{
    const auto range = std::string{"tokyo"};
    boost::copy(range | boost::adaptors::replaced_if([](auto c){ return c == 'o'; }, 'O'), std::ostream_iterator<char>(std::cout, ""));
    std::cout << std::endl;
}

void test_reversed()
{
    const auto range = std::vector<int>{1, 2, 3, 4, 5};
    boost::copy(range | boost::adaptors::reversed, std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;
}

void test_sliced()
{
    const auto range = std::string{"tokyo"};
    boost::copy(range | boost::adaptors::sliced(1, 3), std::ostream_iterator<char>(std::cout, ""));
    std::cout << std::endl;
}

void test_strided()
{
    const auto range = std::string{"!o!y!"};
    boost::copy(range | boost::adaptors::strided(2), std::ostream_iterator<char>(std::cout, ""));
    std::cout << std::endl;
}

void test_tokenized()
{
    auto range = std::string{"[100,200];[300,400];[500,600]"};
    for ( const auto& m : range | boost::adaptors::tokenized(boost::regex(R"(\[\d+,\d+\])")) ) {
        std::cout << m << std::endl;
    }
}

void test_transformed()
{
    auto range = std::vector<int> {1, 2, 3, 4, 5};
    boost::copy(range | boost::adaptors::transformed([](auto i){ return 2 * i; }), std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;
}

void test_uniqued()
{
    auto range = std::vector<int> {1, 1, 3, 4, 4};
    boost::copy(range | boost::adaptors::uniqued, std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;
}

void test_combine()
{
    std::cout << "> combine\n";
    auto v1 = std::vector<int>{1, 2, 3};
    auto v2 = std::vector<std::string>{"tokyo", "osaka", "nagoya"};
    boost::for_each(boost::combine(v1, v2), [](const auto& p){
        std::cout << boost::get<0>(p) << " " << boost::get<1>(p) << std::endl;}
    );
}

int main(int, char* argv[])
{
    test_adjacent_filtered();
    test_copied();
    test_filtered();
    test_indexed();
    test_indirected();
    test_map();
    test_replaced();
    test_replaced_if();
    test_reversed();
    test_sliced();
    test_strided();
    test_tokenized();
    test_transformed();
    test_uniqued();
    test_combine();
    return 0;
}

出力は以下の通り。

> adjacent_filtered
1, 2, 3, 4, 5, 
> copied
20, 30, 
> filtered
0, 2, 4, 6, 8, 
> indexed
3 --- 100
4 --- 101
5 --- 102
6 --- 103
7 --- 104
8 --- 105
9 --- 106
10 --- 107
11 --- 108
12 --- 109
> indirected
10, 20, 30, 
> map
1, 2, 3, 
tokyo, osaka, nagoya, 
> replaced
tOkyO
> replaced_if
tOkyO
> reversed
5 4 3 2 1 
> sliced
ok
> strided
!!!
> tokenized
[100,200]
[300,400]
[500,600]
> transformed
2 4 6 8 10 
> uniqued
1 3 4 
> combine
1 tokyo
2 osaka
3 nagoya