[range-ex] generators

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 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 );

Hi Neal, On Sun, Feb 22, 2009 at 2:05 PM, Neal Becker <ndbecker2@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
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

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

Neil Groves skrev:
Hi Neal,
On Sun, Feb 22, 2009 at 2:05 PM, Neal Becker <ndbecker2@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.
This is difficult, as the underlying std::generate() will pass the object by value anyway.
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?
It would if boost::reference_wrapper<T> provided a perfectly forwarding operator(). Maybe it's time to add that? -Thorsten
participants (3)
-
Neal Becker
-
Neil Groves
-
Thorsten Ottosen