Sprout.Random で次の乱数を取得する

constexpr 時の Sprout.Random は内部の値が変更できない為、標準ライブラリ とは違い operator() を何回呼び出しても同じ値しか返ってきません。
ではどうやって次の乱数値を取得するのかというと operator() を再度呼び出します。

[ソース]

#include <sprout/random.hpp>
#include <iostream>

// n 回分 () の呼び出し
template<typename Gen>
constexpr auto
call_n(Gen&& gen, int index)
->decltype(*gen()){
    return index <= 0 ? *gen() : call_n(gen(), index-1);
}


int
main(){
    static constexpr sprout::hellekalek1995 engine;
    static_assert(engine()   == 2110608584, "");
    static_assert(engine()() == 239248507, "");

    static constexpr sprout::uniform_int_distribution<int> dist1(100, 999);
    
    static_assert(dist1(engine)()       == 200, "");
    static_assert(dist1(engine)()()     == 566, "");
    static_assert(dist1(engine)()()()   == 255, "");
    static_assert(dist1(engine)()()()() == 175, "");

    static_assert(call_n(dist1(engine), 0) == 200, "");
    static_assert(call_n(dist1(engine), 1) == 566, "");
    static_assert(call_n(dist1(engine), 2) == 255, "");
    static_assert(call_n(dist1(engine), 3) == 175, "");

    return 0;
}


おもしろいですね。
(というか考えていたような呼び出し方が既に実装されていた感じ。


あと constexpr ではないけど const じゃない operator() を呼び出した場合は内部の値を変更して標準ライブラリと同じような振る舞いにすれば実行時乱数エンジンとしても使用できるんじゃないかと思った。
……振る舞いが異なるしややこしいかな?