根据value_type调用适当的构造函数:整数或浮点数



我有一个函数,它使用均匀分布用最小值和最大值之间的随机值填充容器。

#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<int>替换std::vector<float>不起作用,因为我必须改用std::uniform_int_distribution。有没有一种简单而优雅的方法可以根据value_type参数选择正确的构造函数?

到目前为止,我一直试图使用std::numeric_limits<typename TContainer::value_type>::is_integer但没有成功。

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

编写一个元函数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>;
};

希望有帮助。

一种解决方案是使用类型特征助手并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);

尝试使用特征类。例如:

template <typename NumType>
struct ValueTraits;
template <>
struct ValueTraits<int>
{        
    using UniformDistributionType = std::uniform_int_distribution<int>;
};

您可以根据类型(然后您可能需要相当多的 Traits 类)或基于布尔值(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);

最新更新