pstade::oven::cycled を使用したときに range として展開して欲しい


つまりこんな感じに展開されて欲しい。

{0,1,2}|cycled(3);              // {{0,1,2},{0,1,2},{0,1,2}}
std::string("無駄")|cycled(3);  // {"無駄","無駄","無駄"}


pstade::oven::cycled は、引数の数だけ range を結合して展開するので、上記のままでは思うように展開されません。

// 実際はこんな感じで展開される
{0,1,2}|cycled(3);              // {0,1,2,0,1,2,0,1,2}
std::string("無駄")|cycled(3);  // {"無駄無駄無駄"}


pstade::oven::cycled に range を渡す前に、pstade::oven::initial_values や pstade::oven::rows 噛ませば思うように展開されます。

using namespace pstade::oven;
{0,1,2}|rows(1, 3)|cycled(3);      // {{0,1,2},{0,1,2},{0,1,2}}
initial_values("無駄")|cycled(3);  // {"無駄","無駄","無駄"}


何をやっているかと言うと、両方とも、cycled に渡す前にいったん、

{0,1,2} → {{0,1,2}}

のような感じに変換してから回展開を行っています。
pstade::oven::rows の場合は、range の長さも指定しないとダメなのでちょっと手間かも。
文字列なんかを複数回展開したい場合に便利ですね。
一種の回避方法なのでもしかしたら正式な処理があるかも知れません。

#include <iostream>

#include <pstade/oven/io.hpp>
#include <pstade/oven/identities.hpp>
#include <pstade/oven/matrix.hpp>
#include <pstade/oven/initial_values.hpp>
#include <pstade/oven/cycled.hpp>
#include <pstade/oven/any_range.hpp>

#include <boost/range/algorithm/for_each.hpp>

int
main(){
    namespace oven = pstade::oven;
    
    int array[3] = {0, 1, 2};
    boost::for_each(
        array|oven::rows(1,3)|oven::cycled(3),
        [](oven::any_range<int, boost::forward_traversal_tag> range){
        std::cout << (range|pstade::oven::identities) << ",";
    });
    std::cout << std::endl;

    std::cout << (oven::initial_values(std::string("無駄"))|oven::cycled(3)) << std::endl;
    
    return 0;
}


[出力]

{0,1,2},{0,1,2},{0,1,2},
{無駄,無駄,無駄}

[pstade]
ver 1.04.3