如果 constexpr 使用尽可能短的代码,我该如何向后移植?

How do I backport if constexpr with the shortest code possible?

本文关键字:constexpr 尽可能 代码 如果      更新时间:2023-10-16

我正在使用此代码来实现类型查询,就像在 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++的环境重写它......部分专业化应该在这里起作用,但它并不那么实用......

完整代码:https://godbolt.org/g/QBs92V

在我的理解中,模拟需要最少额外机械和语法更改的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版本中,同时保持业务逻辑不变。

由于 lambda 是多态的,因此将检查它们的语法正确性,并且只有在评估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);
}