[Random] Passing an arbitrary uniform random number generator to a function

Hello, Suppose that I have a function that takes a uniform random number generator as an argument, e.g. double foo(mt19937 &urng) { double x = uniform_real<double> (0.0, 10.0) (urng); double y = uniform_real<double> (5.0, 7.0) (urng); return (x*y); } Is there a way to make the choice of random number generator arbitrary (i.e. not limited to mt19937) without making the function a template? Alternatively, is there a better way of passing around the basic uniform random number generator? The reason for the no-template rule is that I would like to pass a URNG to a virtual function in a class, and I would really not like to have to make the class itself a template dependent on the type of URNG. Can someone recommend a solution? Thanks and best wishes, -- Joe

Joseph Wakeling wrote:
Hello,
Suppose that I have a function that takes a uniform random number generator as an argument, e.g.
double foo(mt19937 &urng) { double x = uniform_real<double> (0.0, 10.0) (urng); double y = uniform_real<double> (5.0, 7.0) (urng);
return (x*y); }
Is there a way to make the choice of random number generator arbitrary (i.e. not limited to mt19937) without making the function a template? Alternatively, is there a better way of passing around the basic uniform random number generator?
The reason for the no-template rule is that I would like to pass a URNG to a virtual function in a class, and I would really not like to have to make the class itself a template dependent on the type of URNG.
Can someone recommend a solution?
Thanks and best wishes,
-- Joe member func can be template without class class being template.

AMDG Neal Becker wrote:
Joseph Wakeling wrote:
Suppose that I have a function that takes a uniform random number generator as an argument, e.g.
double foo(mt19937 &urng) { double x = uniform_real<double> (0.0, 10.0) (urng); double y = uniform_real<double> (5.0, 7.0) (urng);
return (x*y); }
Is there a way to make the choice of random number generator arbitrary (i.e. not limited to mt19937) without making the function a template? Alternatively, is there a better way of passing around the basic uniform random number generator?
The reason for the no-template rule is that I would like to pass a URNG to a virtual function in a class, and I would really not like to have to make the class itself a template dependent on the type of URNG.
Can someone recommend a solution?
Thanks and best wishes,
member func can be template without class class being template.
A virtual function can't be a template.
You might be able to use something like this:
template<class ResultType>
class runtime_generator {
public:
ResultType min() const { return min_; }
ResultType max() const { return max_; }
ResultType operator()() { return impl(); }
private:
ResultType min_, max_;
boost::function

Steven Watanabe wrote:
A virtual function can't be a template.
... exactly my problem ... :-)
You might be able to use something like this:
template<class ResultType> class runtime_generator { public: ResultType min() const { return min_; } ResultType max() const { return max_; } ResultType operator()() { return impl(); } private: ResultType min_, max_; boost::function
impl; };
I'm sorry, I'm not sure I understand your suggestion. :-( It's not clear to me how Boost's uniform random number generators (URNGs) are meant to be passed around. I'm used to working with the GNU Scientific Library where a URNG is simply a pointer that can be passed around easily, void foo(gsl_rng *r) { // generate some numbers with r ... } ... where of course the particular URNG algorithm may vary. By contrast it's not clear to me how, using Boost's random library, to write code which uses a URNG without specifying its exact type -- unless I use templates. Can you advise? Sorry for my lack of understanding of your suggestion. Thanks & best wishes, -- Joe

Looks like you need some sort of type erasure (Steve's suggestion uses
boost::function for that):
* Create a class that can be passed to uniform_real as a generator -
that is what Steve's runtime_generator class is for.
* Give runtime_generator a constructor that takes a single argument of
a template type, initialize min_ and max_ from that and store the
argument in impl (that will compile if the argument is a rng that
follows the correct conventions)
* Write the virtual function you wanted taking an argument of type
runtime_generator<double>& - but make it private
* Write a non-virtual public template function to wrap the rng
It's difficult to explain concisely - here's what the code should look
like (untested - just for explanation):
template<class ResultType>
class runtime_generator {
public:
template <class T>
explicit runtime_generator(T& rng)
: min_(rng.min()), max_(rng.max()), impl(rng) {
}
ResultType min() const { return min_; }
ResultType max() const { return max_; }
ResultType operator()() { return impl(); }
private:
ResultType min_, max_;
boost::function

Joseph Gauterin wrote:
Looks like you need some sort of type erasure (Steve's suggestion uses boost::function for that):
OK, I think I understand from your description -- thank you, and thanks to Steve as well! What I'm slightly perturbed about is that this seems a slightly complicated way to have to write code that uses an unspecified random number generator -- is there a better way to do the whole RNG thing that I'm missing? Thanks again and best wishes, -- Joe

You're not missing anything - a lot of boost/std/std::tr1 is designed to be used with templates rather than runtime polymorphism - mixing the two isn't trivial. Fortunately, the type erasure method is quite easy to use once you know about it - but it does require a bit of extra work (you don't have to use boost::function for it either - that's just a quick shortcut).

On 04/28/2010 10:45 AM, Joseph Gauterin wrote:
You're not missing anything - a lot of boost/std/std::tr1 is designed to be used with templates rather than runtime polymorphism - mixing the two isn't trivial.
I had a long and careful think about this, and my program design, and
which of the two approaches might actually be more appropriate.
It turns out that, contra my assumptions, a template approach works well
-- it means some changes in the design/philosophy of the classes I'm
building, but I think on balance they are positive changes.
I tried the type erasure method and ran into two problems with it. The
first was that the underlying random number generator isn't itself
updated when runtime_generator is called, despite the use of references.
If you do,
mt19937 rng;
runtime_generator

On Tue, Apr 27, 2010 at 1:50 PM, Joseph Gauterin
Looks like you need some sort of type erasure (Steve's suggestion uses boost::function for that):
* Create a class that can be passed to uniform_real as a generator - that is what Steve's runtime_generator class is for. * Give runtime_generator a constructor that takes a single argument of a template type, initialize min_ and max_ from that and store the argument in impl (that will compile if the argument is a rng that follows the correct conventions) * Write the virtual function you wanted taking an argument of type runtime_generator<double>& - but make it private
Why should the virtual function be private? I suppose the reason to use a virtual function is: * to make it overridable in a derived class * to call it via runtime polymorphism. Making it private don't see how it could work Thank you very much Cheers, -- Marco

Your mention of "you need type erasure" makes me think of using boost::function to do the job, which I suppose could replace the explicit writing of the runtime_generator class. But still, nice idea to wrap the virtual function taking the wrapped thing with a non-virtual template member that does the wrapping.
-----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users- bounces@lists.boost.org] On Behalf Of Joseph Gauterin Sent: Tuesday, April 27, 2010 6:50 AM To: boost-users@lists.boost.org Subject: Re: [Boost-users] [Random] Passing an arbitrary uniform random number generator to a function
Looks like you need some sort of type erasure (Steve's suggestion uses boost::function for that):
* Create a class that can be passed to uniform_real as a generator - that is what Steve's runtime_generator class is for. * Give runtime_generator a constructor that takes a single argument of a template type, initialize min_ and max_ from that and store the argument in impl (that will compile if the argument is a rng that follows the correct conventions) * Write the virtual function you wanted taking an argument of type runtime_generator<double>& - but make it private * Write a non-virtual public template function to wrap the rng
It's difficult to explain concisely - here's what the code should look like (untested - just for explanation):
template<class ResultType> class runtime_generator { public:
template <class T> explicit runtime_generator(T& rng) : min_(rng.min()), max_(rng.max()), impl(rng) { }
ResultType min() const { return min_; } ResultType max() const { return max_; } ResultType operator()() { return impl(); }
private: ResultType min_, max_; boost::function
impl; }; //in your class... public: template<class rng_t> double foo(rng_t& urng) { runtime_generator<double> rtRNG(urng); return foo_(rtRNG); }
private: virtual double foo_(runtime_generator<double> &urng) { double x = uniform_real<double> (0.0, 10.0) (urng); double y = uniform_real<double> (5.0, 7.0) (urng); return (x*y); } _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
TradeStation Group, Inc. is a publicly-traded holding company (NASDAQ GS: TRAD) of three operating subsidiaries, TradeStation Securities, Inc. (Member NYSE, FINRA, SIPC and NFA), TradeStation Technologies, Inc., a trading software and subscription company, and TradeStation Europe Limited, a United Kingdom, FSA-authorized introducing brokerage firm. None of these companies provides trading or investment advice, recommendations or endorsements of any kind. The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer.

Making it private don't see how it could work C++'s private does not prevent ovrerriding (unlike some other languages)
Why should the virtual function be private? The desired interface is a function that takes any type the implements the random double generator 'concept'. Template functions cannot be virtual. That leads to a private virtual function (which can be overridden in derived classes, but not called) and a public template function that calls the private virtual function after translating the argument into a useable form.
More generally, Herb Sutter's recommendation to "prefer to make base class virtual functions private" (http://www.gotw.ca/publications/mill18.htm) is sound advice.

On Thu, Apr 29, 2010 at 11:34 AM, Joseph Gauterin
Making it private don't see how it could work C++'s private does not prevent ovrerriding (unlike some other languages)
Thank you. I admit this were unknown to me. I though that derived classes could override public/protected function only.
Why should the virtual function be private? The desired interface is a function that takes any type the implements the random double generator 'concept'. Template functions cannot be virtual. That leads to a private virtual function (which can be overridden in derived classes, but not called) and a public template function that calls the private virtual function after translating the argument into a useable form.
More generally, Herb Sutter's recommendation to "prefer to make base class virtual functions private" (http://www.gotw.ca/publications/mill18.htm) is sound advice.
Got it! Thank you very much for pointing this article out. Cheers, -- Marco
participants (6)
-
John Dlugosz
-
Joseph Gauterin
-
Joseph Wakeling
-
Marco Guazzone
-
Neal Becker
-
Steven Watanabe