Rokiのチラ裏

学生による学習のログ

make_elements_string

コンテナの要素を全て出力したい事がよくある。一々全て出力するrange based forを書くのは面倒だ。ただ全ての要素を出力するだけなのだから、ネット上のどこかに落ちていそうだが、なんだか見当たらない。
そんなわけで、私は3年前ぐらいに、mikoという名前空間で、rall_coutとoperator <<を定義、オーバーロードする事で、全ての要素を出力するというユーティリティライブラリを作った。 以下がその実装である。しかしこの実装は、3年前のものなので、C++11時代の記述法であったり、iostreamのようなスタイルで記述する事を意識した設計思想で実装した事によって、直接的な意味合いとしては分かりにくい。
そこで、C++1z的な記述法でかつ、あくまで「文字列を生成する」という意味合いを強めたヘルパ関数、make_elements_stringをこの度書いてみた。

ものとしては、コンテナ内の要素全てを指定されたdelimiterで区切り、文字列として生成するというかなり単純なものだ。デフォルトで設定されているdelimiterはspaceである。標準出力ライブラリを用いて、tupleなども含めた、全てのSTLに含まれるコンテナ、コンテナアダプターや生配列の全要素を出力できる。

#include"srook/make_element_string.hpp"
#include<map>
#include<tuple>
#include<string>
#include<iostream>

int main()
{
    using namespace std::string_literals;

    int ar[]{10,20,30,40};
    std::multimap<std::string,int> mp{std::make_pair("hoge"s,42),std::make_pair("foo"s,42)};
    std::tuple<std::string,int,float> t{"hoge"s,42,53.0f};

    std::cout<<srook::make_elements_string(ar)<<std::endl;
    std::cout<<srook::make_elements_string(mp)<<std::endl;
    std::cout<<srook::make_elements_string(t)<<std::endl;
}

以下のように出力される。

10 20 30 40 
[foo 42] [hoge 42] 
hoge 42 53 

イテレータを渡せば、その範囲内を指定されたdelimiterで区切った文字列を生成する。

#include"srook/make_element_string.hpp"
#include<vector>
#include<numeric>
#include<iostream>
#include<algorithm>
int main()
{
    std::vector<int> v(10);
    std::iota(std::begin(v),std::end(v),0);

    std::cout<<
        srook::make_elements_string(std::begin(v),
                std::find(std::begin(v),std::end(v),8))<<std::endl;
}

以下のように出力される。

0 1 2 3 4 5 6 7

delimiterは、テンプレートパラメータに指定する事によって、変更する事ができる。

#include"srook/make_element_string.hpp"
#include<vector>
#include<numeric>
#include<iostream>
#include<algorithm>
int main()
{
    std::vector<int> v(10);
    std::iota(std::begin(v),std::end(v),0);

    std::cout<<
        srook::make_elements_string<','>(std::begin(v),
                std::find(std::begin(v),std::end(v),8))<<std::endl;
}

以下のように出力される。

0,1,2,3,4,5,6,7

delimiterの指定を静的にしたのは、今の所、個人的に区切りとして使う値を動的に変動できなくても用が足りるだろうと判断したためである。また、視覚的な問題も兼ねて。
使っていく中で必要と思い次第、普通の引数として指定できるようにするかもしれないが、必要に思う事はあまりないだろう。
最後にこれは特に意味のない機能であるが、値を入れると、指定した値全てをdelimiterで区切った文字列として生成する。

#include"srook/make_element_string.hpp"
#include<iostream>

int main()
{
    auto s=srook::make_elements_string<','>("foo",10,42.0f);
    std::cout<<s<<std::endl;
}

以下のように出力する。

foo,10,42

...とまあ、これぐらいの機能であれば、本当にどこか他に良い出力ライブラリみたいなものがありそうなものなのだが、今の所見つからないので、作ってみた次第である。
個人的には、デバッグが楽になるので、出来に対して、まあ良いかと思ってはいるが。