Oven meets Boost.Spirit.Karma
Boost.Spiritは元々が*1がパーサージェネレータであったこともあり、Qiが一番有名であると思いますが、Boost.Spirit一家にはKarmaという次男坊(?)がいます。
Spirit.KarmaはSpirit.Qiの逆で、データから文字列を生成するコンビネータ郡です。Performance of Numeric Generators - 1.44.0によると、iostreamやsprintfやBoost.Formatよりも高速であるとされています。また、sprintfと違い型安全な設計となっています。難点は書式指定がやや面倒なことと、コンパイル時間がboostされることですが…。
Boost.Karmaは入力に対して柔軟な設計がされており、Ovenのレンジと組合せて使うことができます。
int main() { std::vector<int> const xs = { 1, 2, 3, 4, 5 }; karma::generate( std::ostreambuf_iterator<char>(std::cout), spirit::karma::int_ % ' ', xs | oven::transformed(std::negate<int>())); return 0; }
たとえば、上記のような記述をすれば、std::vector
また、oven::fuzippedといったアダプタを使えばより複雑なケースに対応することができます。fuzippedはzippedのfusion版です。zippedは型がboost::tupleとなりますが、fuzippedはboost::fusion::vectorとなります。
int main() { std::vector<int> xs = { 1, 2, 3, 4, 5 }; karma::generate( std::ostreambuf_iterator<char>(std::cout), (karma::lit("negate: ") << karma::int_ << " -> " << karma::int_) % karma::eol, egg::pack( xs, xs | oven::transformed(std::negate<int>()) ) | oven::fuzipped ); std::cout << std::endl; return 0; }
このプログラムを実行すると、
negate: 1 -> -1 negate: 2 -> -2 negate: 3 -> -3 negate: 4 -> -4 negate: 5 -> -5
という結果が得られます。
Rangeを文字列に変換できるという特徴は、他のsprintfやiostreamによる実装にはない特徴です。
*1:現在のClassic