random_shuffled range アダプタ

久しぶりに range アダプタでも.
考え方は oven::sorted と同じで,range からイテレータのリストを作り,そのリストをシャッフルします.結果として forward range にも対応できます.
random_shuffled.hpp (要 P-Stade)

#ifndef IORATE_RANDOM_SHUFFLED_HPP
#define IORATE_RANDOM_SHUFFLED_HPP

#include <boost/concept/assert.hpp>
#include <boost/range/algorithm/random_shuffle.hpp>
#include <boost/range/concepts.hpp>
#include <boost/utility/result_of.hpp>
#include <pstade/egg/function.hpp>
#include <pstade/egg/pipable.hpp>
#include <pstade/oven/indirected.hpp>
#include <pstade/oven/outplaced.hpp>

namespace iorate {

    namespace random_shuffled_detail {
        
        using namespace pstade::oven;

        struct little
        {
            template <class Me, class Range, class RandomNumberGenerator = void>
            struct apply
              : boost::result_of<
                    T_make_indirected(
                        typename boost::result_of<T_make_outplaced(Range &)>::type &
                    )
                >
            {};

            template <class Re, class Range>
            Re call(Range &rng) const
            {
                BOOST_CONCEPT_ASSERT((boost::ForwardRangeConcept<Range>));
                typename boost::result_of<T_make_outplaced(Range &)>::type its = rng | outplaced;
                boost::random_shuffle(its);
                return its | indirected;
            }

            template <class Re, class Range, class RandomNumberGenerator>
            Re call(Range &rng, RandomNumberGenerator &rand) const
            {
                BOOST_CONCEPT_ASSERT((boost::ForwardRangeConcept<Range>));
                typename boost::result_of<T_make_outplaced(Range &)>::type its = rng | outplaced;
                boost::random_shuffle(its, rand);
                return its | indirected;
            }
        };

    } // namespace random_shuffled_detail

    typedef pstade::egg::function<random_shuffled_detail::little> T_make_random_shuffled;
    T_make_random_shuffled const make_random_shuffled = {{}};

    pstade::egg::result_of_pipable<T_make_random_shuffled>::type const random_shuffled = PSTADE_EGG_PIPABLE({{}});

} // namespace iorate

#endif

random_shuffle_test.cpp

#include <iostream>
#include <boost/range/irange.hpp>
#include <pstade/oven/io.hpp>
#include "./random_shuffled.hpp"

int main()
{
    std::cout << (boost::irange(0, 10) | iorate::random_shuffled) << '\n';
}
$ g++ -I $BOOST_ROOT -I $PSTADE_ROOT random_shuffle_test.cpp

$ ./a
{8,1,9,2,0,5,7,3,4,6}