我有一个函数,使用均匀分布在min和max之间填充具有随机值的容器。
#include <iostream>
#include <random>
#include <algorithm>
#include <vector>
template<typename TContainer>
void uniform_random(TContainer& container,
const typename TContainer::value_type min,
const typename TContainer::value_type max) {
std::random_device rd;
std::mt19937 gen(rd());
// Below line does not work with integers container
std::uniform_real_distribution<typename TContainer::value_type> distribution(min, max);
auto lambda_norm_dist = [&](){ return distribution(gen); };
std::generate(container.begin(), container.end(), lambda_norm_dist);
}
int main() {
std::vector<float> a(10);
uniform_random(a,0,10);
for (auto el : a) { std::cout << el << " "; }
}
用std::vector<float>
替换std::vector<int>
不起作用,因为我必须使用std::uniform_int_distribution
。
是否有一种简单而优雅的方法可以根据value_type参数选择正确的构造函数?
我到目前为止尝试使用std::numeric_limits<typename TContainer::value_type>::is_integer
但没有成功。
答案 0 :(得分:7)
在C ++ 14(或带有微小变化的C ++ 11)中,您可以用这种方式创建uniform_distribution
类型别名:
template <typename ValueType>
using uniform_distribution = std::conditional_t<
std::is_floating_point<ValueType>::value,
std::uniform_real_distribution<ValueType>,
std::uniform_int_distribution<ValueType>
>;
用法:
uniform_distribution<typename TContainer::value_type> distribution(min, max);
答案 1 :(得分:6)
编写一个元函数select_distribution
,允许你写这个:
using value_type = typename TContainer::value_type;
using distribution_type = typename select_distribution<value_type>::type;
distribution_type distribution(min, max);
其中select_distribution
定义为:
template<typename T, bool = std::is_floating_point<T>::value>
struct select_distribution
{
using type = std::uniform_real_distribution<T>;
};
template<typename T>
struct select_distribution<T, false>
{
using type = std::uniform_int_distribution<T>;
};
希望有所帮助。
答案 2 :(得分:4)
一种解决方案是使用类型特质助手和std::enable_if
:
template<class T, class Enable = void>
struct uniform_distribution_helper {};
template<class T>
struct uniform_distribution_helper<T, typename std::enable_if<std::is_floating_point<T>::value >::type> {
using type = std::uniform_real_distribution<T>;
};
template<class T>
struct uniform_distribution_helper<T, typename std::enable_if<std::is_integral<T>::value >::type> {
using type = std::uniform_int_distribution<T>;
};
然后在你的函数中:
using uniform_distribution = typename uniform_distribution_helper<typename TContainer::value_type>::type;
// Below line does not work with integers container
uniform_distribution distribution(min, max);
答案 3 :(得分:0)
尝试使用traits类。例如:
template <typename NumType>
struct ValueTraits;
template <>
struct ValueTraits<int>
{
using UniformDistributionType = std::uniform_int_distribution<int>;
};
您可以根据类型(然后您可能需要相当多的Traits类)或基于bool值(is_integer的结果)来执行此操作,然后您需要为using
模板化
然后在你的班上:
// In the class scope:
typedef TContainer::value_type value_type;
// And in your constructor:
typename ValueTraits<value_type>::UniformDistributionType distribution(min, max);