読者です 読者をやめる 読者になる 読者になる

ゆとりーなの日記

日記的な事を書いて行くと思はれる

pstade::oven::string_splitの使い方

が今迄よく分かってなかったのですが、今宵判明したのでメモメモです。
先ず、似たようなものにBoost.String Algorithmsというのがあります。文字列を特定の文字で分割するときは次のように書けます。

#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <pstade/oven/algorithm.hpp>

int main() {
  std::string const message = "This is a pen";
  std::vector<std::string> v;
  boost::algorithm::split(v, message, boost::algorithm::is_space());
  pstade::oven::for_each(v, [](std::string const &x) {
    std::cout << x << std::endl;
  });
  return 0;
}
出力
This
is
a
pen

しうしこれだと我々の至高であるconstをstd::vectorに対して付けてやることが出来ません。vは変更する予定がないのにconstが付いてないとか落ち着きませんね。
そこでovenにstring_splitなるものがあるので、これを使って同じ様なことが出来ないかという模索が始まりました。
取り敢えずpstade::oven::string_splitの使い方が知りたかったのでリファレンス(英語で凄く厄介)を見たところアダプタだということが判明したので、最初多分こんな感じに使うんだろうなぁと思って書いてみました。

#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <pstade/oven/algorithm.hpp>
#include <pstade/oven/string_split.hpp>
#include <pstade/oven/copied.hpp>

int main() {
  std::string const message = "This is a pen";
  std::vector<std::string const> const v = message | pstade::oven::string_split(boost::algorithm::is_space()) | pstade::oven::copied;
  pstade::oven::for_each(v, [](std::string const &x) {
    std::cout << x << std::endl;
  });
  return 0;
}

コンパイルでこける余裕でした。足りない英語力でリファレンスをもう一度凝視したところ、string_splitが取る引数はFinderなるものだということが判明したので、Finderとはなんぞやと調べる羽目になりました。まぁ雰囲気Boost.String Algorithms関連のとこにあるだろうなというアタリを付けて見てみたら案の定ありました。boost::algorithm::token_finderでboost::algorithm::is_spaceを括ってやればいいことが判明したので早速試してみました。

#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <pstade/oven/algorithm.hpp>
#include <pstade/oven/string_split.hpp>
#include <pstade/oven/copied.hpp>

int main() {
  std::string const message = "This is a pen";
  std::vector<std::string const> const v = message | pstade::oven::string_split(boost::algorithm::token_finder(boost::algorithm::is_space())) | pstade::oven::copied;
  pstade::oven::for_each(v, [](std::string const &x) {
    std::cout << x << std::endl;
  });
  return 0;
}

はい、でもまだこけるんです。どうやらpstade::oven::copiedの部分でこけてるらしいのです。std::stringにcopiedが使えないというのは割と有名な話なのでそれが絡んでるんだろうなぁと半ば諦めていたのですが、Twitterでokomokさんのリプライで全てが解決しました。

string_splitはiterator_rangeのrangeになります。|oven::transformed(oven::make_copied) をstring_split(..)のあとに挟んでみてください

これかーと思い早速試してみました。

#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <pstade/oven/algorithm.hpp>
#include <pstade/oven/string_split.hpp>
#include <pstade/oven/copied.hpp>

int main() {
  std::string const message = "This is a pen";
  std::vector<std::string const> const v = message | pstade::oven::string_split(boost::algorithm::token_finder(boost::algorithm::is_space())) | pstade::oven::transformed(pstade::oven::make_copied) | pstade::oven::copied;
  pstade::oven::for_each(v, [](std::string const &x) {
    std::cout << x << std::endl;
  });
  return 0;
}
出力
This
is
a
pen

いけましたー。しかし横に凄く長くなってしまったという難点が。using namespace使えば短く書けますが、あれは余り好かんのです。