我如何使用 "if constexpr" 正确实施 "operator()" 以使其与 std::generate 一起使用?
How do I properly implement "operator()" with "if constexpr" so that it works with std::generate?
我正在尝试编写一个 class 来填充一个容器,其中包含容器具有的类型的随机数:
template<typename random_type>
class rand_helper {
private:
std::mt19937 random_engine;
std::uniform_int_distribution<int> int_dist;
std::uniform_real_distribution<double> real_dist;
public:
rand_helper() = delete;
rand_helper(random_type left_b, random_type right_b);
random_type operator()();
};
template<typename random_type>
rand_helper<random_type>::rand_helper(const random_type left_b, const random_type right_b) :random_engine{ std::random_device{}()} {
if constexpr (std::is_same_v<random_type, double>)
real_dist(left_b, right_b );
else
int_dist( left_b, right_b );
}
template<typename random_type>
random_type rand_helper<random_type>::operator()() {
if constexpr (std::is_same_v<random_type, double>)
return real_dist(random_engine);
else
return int_dist(random_engine);
}
但是这里某处发生了错误,因为当我调用std::generate时,我得到了很多错误:
template<typename T,typename vec_type = typename T::value_type>
void fill_contain(T& container,vec_type left_b=vec_type(0), vec_type right_b= vec_type(100)) {
std::generate(std::begin(container),std::end(container), rand_helper<vec_type>(left_b ,right_b));
}
我认为可能是因为 if constexpr 但如果只是离开:
template<typename random_type>
random_type rand_helper<random_type>::operator()() {
return int_dist(random_engine);
}
然后仍然返回相同的错误。
这是我得到的错误列表:
Error C2825 '_Urng': must be a class or namespace when followed by '::'
Error C2510 '_Urng' : left of '::' must be a class / struct / union
Error C2061 syntax error : identifier 'result_type'
Error C2065 '_Ty1' : undeclared identifier
Error C2923 'std::conditional_t' : '_Ty1' is not a valid template type argument for parameter '_Ty2'
函数调用是这样的:
std::vector<int> for_sort;
fill_contain(for_sort);
无论 if constexpr
,您的代码都无法编译。仅使用模板 class 可能不会出现编译错误的原因是,好吧,它是一个模板,因此不会编译任何实际实例。如果您添加:
template class rand_helper<int>;
强制实例化 random_type
of int
,你会得到大量的编译错误输出。
具体来说,您会被告知您需要一个伪随机数生成器来构造一个 uniform_int_distribution<int>
。
不管上面是什么 - 你可以使用类似的东西:
template <typename T>
using uniform_distribution = std::conditional_t<
std::is_integral_v<T>,
std::uniform_int_distribution<T>,
std::uniform_real_distribution<T>
>;
只有一个分发成员。在那种情况下,你甚至可能不需要你的助手 class.
为了避免使用非浮点类型实例化 std::uniform_real_distribution
模板 class 并获得可能令人困惑的诊断,我更愿意使用这样的模板特化而不是 std::conditional_t
:
namespace detail
{
template <typename T, typename AlwaysVoid = void>
struct uniform_distribution_impl
{
static_assert(sizeof(T) == 0, "T must be integral or floating point");
};
template <typename T>
struct uniform_distribution_impl<
T, std::enable_if_t<std::is_integral_v<T>>>
{
using type = std::uniform_int_distribution<T>;
};
template <typename T>
struct uniform_distribution_impl<
T, std::enable_if_t<std::is_floating_point_v<T>>>
{
using type = std::uniform_real_distribution<T>;
};
}
template <typename T>
using uniform_distribution = typename detail::uniform_distribution_impl<T>::type;
我正在尝试编写一个 class 来填充一个容器,其中包含容器具有的类型的随机数:
template<typename random_type>
class rand_helper {
private:
std::mt19937 random_engine;
std::uniform_int_distribution<int> int_dist;
std::uniform_real_distribution<double> real_dist;
public:
rand_helper() = delete;
rand_helper(random_type left_b, random_type right_b);
random_type operator()();
};
template<typename random_type>
rand_helper<random_type>::rand_helper(const random_type left_b, const random_type right_b) :random_engine{ std::random_device{}()} {
if constexpr (std::is_same_v<random_type, double>)
real_dist(left_b, right_b );
else
int_dist( left_b, right_b );
}
template<typename random_type>
random_type rand_helper<random_type>::operator()() {
if constexpr (std::is_same_v<random_type, double>)
return real_dist(random_engine);
else
return int_dist(random_engine);
}
但是这里某处发生了错误,因为当我调用std::generate时,我得到了很多错误:
template<typename T,typename vec_type = typename T::value_type>
void fill_contain(T& container,vec_type left_b=vec_type(0), vec_type right_b= vec_type(100)) {
std::generate(std::begin(container),std::end(container), rand_helper<vec_type>(left_b ,right_b));
}
我认为可能是因为 if constexpr 但如果只是离开:
template<typename random_type>
random_type rand_helper<random_type>::operator()() {
return int_dist(random_engine);
}
然后仍然返回相同的错误。 这是我得到的错误列表:
Error C2825 '_Urng': must be a class or namespace when followed by '::'
Error C2510 '_Urng' : left of '::' must be a class / struct / union
Error C2061 syntax error : identifier 'result_type'
Error C2065 '_Ty1' : undeclared identifier
Error C2923 'std::conditional_t' : '_Ty1' is not a valid template type argument for parameter '_Ty2'
函数调用是这样的:
std::vector<int> for_sort;
fill_contain(for_sort);
无论 if constexpr
,您的代码都无法编译。仅使用模板 class 可能不会出现编译错误的原因是,好吧,它是一个模板,因此不会编译任何实际实例。如果您添加:
template class rand_helper<int>;
强制实例化 random_type
of int
,你会得到大量的编译错误输出。
具体来说,您会被告知您需要一个伪随机数生成器来构造一个 uniform_int_distribution<int>
。
不管上面是什么 - 你可以使用类似的东西:
template <typename T>
using uniform_distribution = std::conditional_t<
std::is_integral_v<T>,
std::uniform_int_distribution<T>,
std::uniform_real_distribution<T>
>;
只有一个分发成员。在那种情况下,你甚至可能不需要你的助手 class.
为了避免使用非浮点类型实例化 std::uniform_real_distribution
模板 class 并获得可能令人困惑的诊断,我更愿意使用这样的模板特化而不是 std::conditional_t
:
namespace detail
{
template <typename T, typename AlwaysVoid = void>
struct uniform_distribution_impl
{
static_assert(sizeof(T) == 0, "T must be integral or floating point");
};
template <typename T>
struct uniform_distribution_impl<
T, std::enable_if_t<std::is_integral_v<T>>>
{
using type = std::uniform_int_distribution<T>;
};
template <typename T>
struct uniform_distribution_impl<
T, std::enable_if_t<std::is_floating_point_v<T>>>
{
using type = std::uniform_real_distribution<T>;
};
}
template <typename T>
using uniform_distribution = typename detail::uniform_distribution_impl<T>::type;