Boost logo

Boost :

Subject: Re: [boost] [range-ex] generators
From: Neal Becker (ndbecker2_at_[hidden])
Date: 2009-02-22 09:56:45


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> > >) ()’


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk