
Neil Groves <neil <at> grovescomputing.com> writes:
Hi Neal,
On Sun, Feb 22, 2009 at 2:05 PM, Neal Becker <ndbecker2 <at> gmail.com> wrote:
I have a question of generate. I believe one usually wants generators to have state. Yet, generator is passed by value. This is awkward, the workaround is to manually specify
I have rather blindly followed the standard and passed the Generator by value. I am open to deviate if there is sufficient justification.
generate<ForwardRange, Generator&>( rng, gen );
Since Generator is the 2nd template parameter we must specify ForwardRange, which might be complicated.
I wonder if we should have: template<class ForwardRange, class Generator> ForwardRange& generate( ForwardRange& rng, Generator & gen );
My usual technique which I apply to for_each and most of the other standard algorithm functions is to use boost::ref. The standard library passes almost all functors and predicates by value. I can only remember some of the random_... functions passing the random generator by reference.
Therefore we can avoid specifying the ForwardRange thus:
generate(rng, ref(gen));
I am concerned that if it is wrong for generate, then it may well be wrong for many of the other algorithms that take functors and predicates. I believe that defaulting to pass by value improves the efficiency for many small functors.
Would someone please enlighten me with the rationale for passing by value in the standard version?
Does the use of boost::ref sufficiently address your concerns?
Cheers, Neil Groves
Like this? #include <boost/random.hpp> #include <boost/range.hpp> #include <boost/range/algorithm.hpp> #include <vector> #include <boost/ref.hpp> int main() { typedef boost::mt19937 rng_t; rng_t rng; boost::variate_generator<rng_t&, boost::uniform_real<> > gen (rng, boost::uniform_real<> (0, 10)); std::vector<double> v (10); boost::generate (v, ref (gen)); } g++ -c -I /usr/local/src/boost_1_38_0_range_ex.hg/ test1.cc /usr/lib/gcc/x86_64-redhat- std::generate(_FIter, _FIter, _Generator) [with _FIter = __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double>
, _Generator = boost::reference_wrapper<boost::variate_generator<main()::rng_t&, boost::uniform_real<double> > >]’: /usr/local/src/boost_1_38_0_range_ex.hg/boost/range/algorithm/generate.hpp:30: instantiated from ‘ForwardRange& boost::generate(ForwardRange&, Generator) [with ForwardRange = std::vector<double, std::allocator<double> >, Generator = boost::reference_wrapper<boost::variate_generator<main()::rng_t&, boost::uniform_real<double> > >]’ test1.cc:15: instantiated from here /usr/lib/gcc/x86_64-redhat- for call to ‘(boost::reference_wrapper<boost::variate_generator<main()::rng_t&, boost::uniform_real<double> > >) ()’