🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

C++ hat random container

Started by
53 comments, last by GameDev.net 19 years, 7 months ago
Quote: Original post by AngleWyrm
Could you give an example of #2, show what is meant by non-type vs type parameter


an example of a non-type template parameter from your hat containers would be:

template <class T, unsigned long (*random)(unsigned long) = std_rand>


talking about the function pointer random, doing this is inflexible, remember that templates are a compile time mechanism
it allows you to perform static polymorphism where as function pointer is a run-time feature it incurs one level of indirection overhead that isn't needed.

if you change it to a type parameter e.g.:

template < typename T, typename Random = std_rand>


then you can use almost anything functors & functions.

Quote:
and how a functor operator() could be advantageous?


its strange that you know STL and you haven't come across functors before, STL use functors alot and they even provide some, mainly in the header functional.

The first reason for the operator() is that when your code realise on that operator then not only can you use types that overload operator() but you can use functions as a type for template type parameter aswell.

the advantage of functors are they are inlineable, they can maintain state, they can be configured through constructors.

Here is really simplified example of a the function generate that first uses the function rand then another call using a functor:

#include <cmath>#include <iterator>#include <algorithm>#include <functional>#include <vector>#include <iostream>struct Random {   int operator()() const {        return ::rand();   }  };template< typename T, typename Iter>void print_elems(Iter beg, Iter end) {   std::copy(beg, end,             std::ostream_iterator<T>(std::cout, ", "));}   int main() {   std::vector<int> vec_of_ints(10);   //using a function rand   std::generate(vec_of_ints.begin(),                 vec_of_ints.end(),                 ::rand);   print_elems<int>(vec_of_ints.begin(), vec_of_ints.end());   //using a functor Random   std::generate(vec_of_ints.begin(),                 vec_of_ints.end(),                 Random());   std::cout << "\n\n";   print_elems<int>(vec_of_ints.begin(), vec_of_ints.end());   return 0;}


std::generate uses a type parameter for the Generator type and not a non-type parameter, you can use anything that supports the function call operator () that includes functions this is static polymorphism.

[Edited by - snk_kid on September 1, 2004 3:28:34 AM]
Advertisement
std::rand() is called without arguments, and produces a result in the range [0, RAND_MAX), whereas what is required is a number in the range [0, range) where range is specified at run-time.
std::rand() % range
does not produce good results (Linear Congruential generators produce hyperplanes in higher dimensions, rather than filling the space randomly). So I have created a function adaptor that provides a good conversion of the range [0, RAND_MAX) to any scale within my usage domain for std::rand().

For user-supplied custom RNGs, it would be an improbable assumption to suggest that the construct random() % range is going to perform well, a demand not placed on std::rand(). Thus what is required is that a user-supplied RNG also provide the method of scaling.

It is my opinion that a custom RNG is not a usable implementation until it provides it's user with a method of specifying a range at run-time.

[Edited by - AngleWyrm on September 1, 2004 10:30:43 AM]
--"I'm not at home right now, but" = lights on, but no ones home
Quote: Original post by AngleWyrm
It is my opinion that a custom RNG is not a usable implementation until it provides it's user with a method of specifying a range at run-time.


i was just showing an example of functors it wasn't mean't to be used in your implementation in any kind of way. And yes you can still provide a range at run-time with a functor if you wonted to be it one time or everytime you call it, overloading operator() doesn't mean it must have no argumenets.
Actually, I was thinking more of the boost::random library when I went on a rant back there ;) Their implementation seems to require a range object be constructed and then passed to the random number generator's constructor, which will then only roll that range for it's duration. Hope I'm wrong, but I haven't seen different.

Updated query functions such as empty(), get_weight(), size(), etc, to be const.

[Edited by - AngleWyrm on September 2, 2004 11:32:29 PM]
--"I'm not at home right now, but" = lights on, but no ones home
Quote: Original post by Fruny
What are the exception guarantees of your class? What happens during, say, a pull(), if the element's copy operation throws an exception?


It is a requirement that objects in a hat container are assignable. The pull() function uses a call of the operator=() assignment to a user supplied buffer.

If the operator=() call to a user-supplied item throws an exception? Is this possible, and if so should it be the container's responsibility to do error checking for it?
First, the documentation looks excellent. Cool graphics and css. And the code and the examples are also easy to read.

But the lib itself could use some work. Now it seems to me that it can't use a random generator object that has it's own state. Relying on global state is sometimes dangerous or just wrong. You should make it easily integratable with boost's rngs like others have suggested. You can get dynamic range by doing uniform_int<>(low, high)(engine). Ok so it means constructing small objects every time, but that is also what uniform_int itself does so I doubt it's that slow relatively (test it).

Also it could be possible to have another strategy for the selection of items, that is a look-up-table. Let the user choose which selection strategy to use (and of course to create their own strategies)
Thanks for the compliment, and the constructive criticisms.

Could you go into a little detail about alternate selection methods? pseudo-code or fictional functions/usage scenarios? Examples? They help me to see the problem from different perspectives. It recently seemed as if the current implementation might be too focused on it's original purpose, and that it could serve a wider scope of uses.

Also, gave boost::random another go (Boost::random_number_generator) but I haven't got randomness out of boost yet; anyone with experience using the boost::random library, please tell me how this should be written:

#include <iostream> // cout#include "boost/random.hpp"int main(){   // select generator   boost::minstd_rand rng; // minimum standard random number generator      rng.seed( time(NULL) ); // seeding an instance   // create a function object   boost::random_number_generator<boost::minstd_rand> random(rng);   // this produces the same number every time,   // possibly the first number after seeding?   for( int i = 1; i < 5; i++ ){      std::cout << random(100) << std::endl; // wanted [0..99]  }     }


[Edited by - AngleWyrm on September 5, 2004 10:01:13 AM]
--"I'm not at home right now, but" = lights on, but no ones home

Version 1.50 is Up


Due to popular demand, there is a new interface for specifying custom random number generator objects (yep) at run-time. example usage:
class rng_functor { /* custom rng */ };       // defines operator()(range)rng_functor my_instance;                      // do initializationshat<string, rng_functor> names(my_instance);  // hat using custom rng

Also added some new example programs,
and updated commentary for clearer comprehension.

-:|:-
AngleWyrm

[Edited by - AngleWyrm on September 5, 2004 11:40:38 AM]
--"I'm not at home right now, but" = lights on, but no ones home
sounds good, let me try it:)
i get:

multiple definition of `std_rand'
first defined here
multiple definition of `std_rand'
first defined here
multiple definition of `std_rand'
first defined here
multiple definition of `std_rand'
first defined here
multiple definition of `std_rand'
first defined here
...
...
...


with the new version?? :/ ?

This topic is closed to new replies.

Advertisement