0

i need to write template of function which gets type eg. int, and then it generates random value from MIN_INT to MAX_INT

template<typename TYPE>
TYPE generateRandom()
{
    srand(static_cast<unsigned int>(time(nullptr)));
    TYPE generatedValue;
    //code :/
    return generatedValue;
}

few problems here:

  • rand generate to0 small value (RAND_MAX)
  • in rand i can't do INT_MAX+1 to include int max and negative values

I tried also something like this:

std::random_device randomDevice;
std::mt19937_64 generator(randomDevice());

if(std::numeric_limits<TYPE>::is_integer)
{
    std::uniform_int_distribution<TYPE> dice(std::numeric_limits<TYPE>::min(),std::numeric_limits<TYPE>::max());
    generatedValue=dice(generator);
}
else
{
    std::uniform_real_distribution<TYPE> dice(std::numeric_limits<TYPE>::min(),std::numeric_limits<TYPE>::max());
    generatedValue=dice(generator);
}

but it didnt work :/

R Sahu
  • 204,454
  • 14
  • 159
  • 270

1 Answers1

0

Your problem is that you have an if/else branch like you would use for run time value checks. You need compile time branching using template metaprogramming techniques.

Something along the lines of the following should work.

template <typename TYPE>
std::uniform_int_distribution<TYPE> getDice(std::true_type)
{
   return std::uniform_int_distribution<TYPE>(std::numeric_limits<TYPE>::min(), std::numeric_limits<TYPE>::max());
}

template <typename TYPE>
std::uniform_real_distribution<TYPE> getDice(std::false_type)
{
   return std::uniform_real_distribution<TYPE>(std::numeric_limits<TYPE>::min(), std::numeric_limits<TYPE>::max());
}

template<typename TYPE>
TYPE generateRandom()
{
   std::random_device randomDevice;
   std::mt19937_64 generator(randomDevice());
   auto dice = getDice<TYPE>(std::integral_constant<bool, std::numeric_limits<TYPE>::is_integer>());
   return dice(generator);
}

See it working at https://ideone.com/d7Ajfk.

If you are able to use C++17, you can use code that is similar to what you are trying by using if constexpr

template<typename TYPE>
TYPE generateRandom()
{
   std::random_device randomDevice;
   std::mt19937_64 generator(randomDevice());
   if constexpr ( std::numeric_limits<TYPE>::is_integer )
   {
      std::uniform_int_distribution<TYPE> dice(std::numeric_limits<TYPE>::min(), std::numeric_limits<TYPE>::max());
      return dice(generator);
   }
   else
   {
      std::uniform_real_distribution<TYPE> dice(std::numeric_limits<TYPE>::min(), std::numeric_limits<TYPE>::max());
      return dice(generator);
   }
}

Although, I would still encourage using a separate function getDice()

template <typename TYPE>
auto getDice(std::true_type)
{
   if constexpr ( std::numeric_limits<TYPE>::is_integer )
   {
      return std::uniform_int_distribution<TYPE>(std::numeric_limits<TYPE>::min(), std::numeric_limits<TYPE>::max());
   }
   else
   {
      return std::uniform_real_distribution<TYPE>(std::numeric_limits<TYPE>::min(), std::numeric_limits<TYPE>::max());
   }
}

template<typename TYPE>
TYPE generateRandom()
{
   std::random_device randomDevice;
   std::mt19937_64 generator(randomDevice());
   auto dice = getDice<TYPE>();
   return dice(generator);
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270