我使用此代码来实现类似C#中的类型查询:
template<class T>
constexpr bool IsSixtyFourBit() {
return is_same<T, int64_t>() || is_same<T, uint64_t>();
}
template<class T>
constexpr bool IsDouble() {
return is_same<T, double>() || is_same<T, double_t>();
}
template<class T>
constexpr bool IsFloat() {
return is_same<T, float>() || is_same<T, float_t>();
}
template<class T>
constexpr bool IsReal() {
return IsDouble<T>() || IsFloat<T>();
}
template <class T>
constexpr T MakePseudoNumberGenerator(T min, T max) {
if constexpr (IsSixtyFourBit<T>()) {
mt19937_64 rng(random_device{}()); // random-number engine used (Mersenne-Twister in this case)
uniform_int_distribution<T> uni(min, max); // guaranteed unbiased
return uni(rng);
} else if constexpr (IsReal<T>()) {
mt19937_64 rng(random_device{}()); // random-number engine used (Mersenne-Twister in this case)
uniform_real_distribution<T> uni(min, max); // guaranteed unbiased
return uni(rng);
} else {
mt19937 rng(random_device{}()); // random-number engine used (Mersenne-Twister in this case)
uniform_int_distribution<T> uni(min, max); // guaranteed unbiased
return uni(rng);
}
}
但我无法弄清楚如何使用最少的代码在C ++ 17下为C ++环境重写它...部分专业化应该在这里工作,但它不是那么实用......
答案 0 :(得分:2)
根据我的理解,模拟需要最少额外机制和语法变化的if constexpr
的方法是使用std::tuple
。一般方法是翻译代码
if constexpr (P) {
T;
} else {
F;
}
调用封装真假分支的两个多态lambda中的一个:
std::get<P ? 0 : 1>(std::forward_as_tuple(
[&](auto) { T; },
[&](auto) { F; }))(0);
这允许将谓词和两个分支保持在相同的顺序和相同的封闭范围内;事实上,可以将仿真代码放在宏检查__cplusplus
版本中,同时保持业务逻辑不变。
由于lambdas是多态的,因此将检查它们的语法正确性,并且仅在评估P
时进行实例化。
例如,在您的情况下:
template <class T>
constexpr T MakePseudoNumberGenerator(T min, T max) {
return std::get<IsSixtyFourBit<T>() ? 0 : 1>(std::forward_as_tuple(
[&](auto) {
mt19937_64 rng(random_device{}()); // random-number engine used (Mersenne-Twister in this case)
uniform_int_distribution<T> uni(min, max); // guaranteed unbiased
return uni(rng);
}, std::get<IsReal<T>() ? 0 : 1>(std::forward_as_tuple(
[&](auto) {
mt19937_64 rng(random_device{}()); // random-number engine used (Mersenne-Twister in this case)
uniform_real_distribution<T> uni(min, max); // guaranteed unbiased
return uni(rng);
},
[&](auto) {
mt19937 rng(random_device{}()); // random-number engine used (Mersenne-Twister in this case)
uniform_int_distribution<T> uni(min, max); // guaranteed unbiased
return uni(rng);
}))))(0);
}