c++ - specializing a template on bool + integral + floating-point return types -
i'd write function template returns random variable of various types (bool, char, short, int, float, double, along unsigned versions of these).
i couldn't see how using latest c++11 standard library, since need use either uniform_int_distribution or uniform_real_distribution. thought specialize template:
template<typename t> t randomprimitive() { std::uniform_int_distribution<t> dst; std::mt19937 rng; return dst(rng); } template<> bool randomprimitive<bool>() { std::uniform_int_distribution<signed char> dst; std::mt19937 rng; return dst(rng) >= 0 ? true : false; } template<typename t> typename std::enable_if<std::is_floating_point<t>::value, t>::type randomprimitive() { std::uniform_real_distribution<t> dst; std::mt19937 rng; return dst(rng); }
under visual studio 2012 update 3, gives:
error c2668: '`anonymous-namespace'::randomprimitive' : ambiguous call overloaded function
when try compile:
randomprimitive<float>();
is there way specialize function template can write 3 different implementations bool, other integral types, , floating-point types?
you're getting close edits. need restrict "integral" version integral types. rid of ambiguity:
template<typename t> typename std::enable_if < std::is_integral<t>::value, t >::type randomprimitive()
but if run this:
#include <iostream> int main() { (int = 0; < 10; ++i) std::cout << randomprimitive<float>() << '\n'; (int = 0; < 10; ++i) std::cout << randomprimitive<double>() << '\n'; (int = 0; < 10; ++i) std::cout << (int)randomprimitive<signed char>() << '\n'; (int = 0; < 10; ++i) std::cout << randomprimitive<unsigned>() << '\n'; (int = 0; < 10; ++i) std::cout << randomprimitive<bool>() << '\n'; }
you'll like:
0.814724 0.814724 0.814724 0.814724 0.814724 0.814724 0.814724 0.814724 0.814724 0.814724 0.135477 0.135477 0.135477 0.135477 0.135477 0.135477 0.135477 0.135477 0.135477 0.135477 92 92 92 92 92 92 92 92 92 92 3499211612 3499211612 3499211612 3499211612 3499211612 3499211612 3499211612 3499211612 3499211612 3499211612 1 1 1 1 1 1 1 1 1 1
getting there, not random. problem constructing new engine every time use it. want create urng once, , keep getting random bits out of it:
std::mt19937& get_eng() { static std::mt19937 eng; return eng; }
and should create distributions once too. of them stateless, not of them. best assume of them carry state, , don't want throw state away.
static std::uniform_real_distribution<t> dst;
this improve things, you're not there yet:
0.814724 0.135477 0.905792 0.835009 0.126987 0.968868 0.913376 0.221034 0.632359 0.308167 0.547221 0.188382 0.992881 0.996461 0.967695 0.725839 0.98111 0.109862 0.798106 0.297029 92 13 49 122 46 7 105 45 43 8 2816384844 3427077306 153380495 1551745920 3646982597 910208076 4011470445 2926416934 2915145307 1712568902 0 1 1 1 1 0 1 0 1 0
i note 10 of values signed char
positive. doesn't right. turns out std::uniform_int_distribution
has constructor looks this:
explicit uniform_int_distribution(inttype = 0, inttype b = numeric_limits<inttype>::max());
i'm guessing that's not want, so:
static std::uniform_int_distribution<t> dst(std::numeric_limits<t>::min(), std::numeric_limits<t>::max());
and finally, if want random bool
, go std::bernoulli_distribution
.
putting together:
#include <random> std::mt19937& get_eng() { static std::mt19937 eng; return eng; } template<typename t> typename std::enable_if < std::is_integral<t>::value, t >::type randomprimitive() { static std::uniform_int_distribution<t> dst(std::numeric_limits<t>::min(), std::numeric_limits<t>::max()); return dst(get_eng()); } template<> bool randomprimitive<bool>() { static std::bernoulli_distribution dst; return dst(get_eng()); } template<typename t> typename std::enable_if < std::is_floating_point<t>::value, t >::type randomprimitive() { static std::uniform_real_distribution<t> dst; return dst(get_eng()); } #include <iostream> int main() { (int = 0; < 10; ++i) std::cout << randomprimitive<float>() << '\n'; (int = 0; < 10; ++i) std::cout << randomprimitive<double>() << '\n'; (int = 0; < 10; ++i) std::cout << (int)randomprimitive<signed char>() << '\n'; (int = 0; < 10; ++i) std::cout << randomprimitive<unsigned>() << '\n'; (int = 0; < 10; ++i) std::cout << randomprimitive<bool>() << '\n'; }
which me outputs:
0.814724 0.135477 0.905792 0.835009 0.126987 0.968868 0.913376 0.221034 0.632359 0.308167 0.547221 0.188382 0.992881 0.996461 0.967695 0.725839 0.98111 0.109862 0.798106 0.297029 92 13 -79 -6 46 -121 -23 45 43 8 2816384844 3427077306 153380495 1551745920 3646982597 910208076 4011470445 2926416934 2915145307 1712568902 0 1 1 1 1 0 1 0 1 0
and if still isn't outputting intended, you've got enough direction take here.
Comments
Post a Comment