首页 > 解决方案 > 生成每种类型的从最小值到最大值的随机值的模板函数

问题描述

我需要编写获取类型的函数模板,例如。int,然后生成从 MIN_INT 到 MAX_INT 的随机值

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

这里有几个问题:

我也尝试过这样的事情:

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

但它没有用:/

标签: c++templatesmathrandom

解决方案


您的问题是您有一个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);
}

推荐阅读