模板函数可生成每种类型的最小值到最大值的随机值

时间:2019-01-08 22:34:20

标签: c++ templates math random

我需要编写功能模板,例如。 int,然后生成从MIN_INT到MAX_INT的随机值

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

这里有几个问题:

  • rand生成0个小值(RAND_MAX
  • rand中,我无法INT_MAX+1包含int max和负值

我也尝试过这样的事情:

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

但是它没有用:/

1 个答案:

答案 0 :(得分:0)

您的问题是您有一个if/else分支,就像用于运行时值检查一样。您需要使用模板元编程技术进行编译时分支。

应该遵循以下步骤。

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

查看它在https://ideone.com/d7Ajfk上的运行情况。

如果您能够使用C ++ 17,则可以使用与您尝试使用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);
   }
}

尽管如此,我仍然鼓励使用单独的功能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);
}