【发布时间】:2020-08-15 21:51:21
【问题描述】:
如果没有溢出,我需要一个函数,它会给我“std::ratio_multiply”类型,或者如果溢出,则为我提供原始比率类型列表。
【问题讨论】:
标签: c++ templates stl metaprogramming template-meta-programming
如果没有溢出,我需要一个函数,它会给我“std::ratio_multiply”类型,或者如果溢出,则为我提供原始比率类型列表。
【问题讨论】:
标签: c++ templates stl metaprogramming template-meta-programming
充分条件是检查分子和分母的对数总和是否小于std::numeric_traits<std::intmax_t>::max() 的对数,但这不包括一些会取消为可表示值的事物。
这可以通过考虑 gcds 来改善
template <typename R1, typename R2, bool>
struct safe_ratio_multiply_impl;
template <typename R1, typename R2>
struct safe_ratio_multiply_impl<R1, R2, true>
{
using type = std::ratio_multiply<R1, R2>;
}
template <typename R1, typename R2>
struct safe_ratio_multiply_impl<R1, R2, false>
{
using type = std::tuple<R1, R2>;
}
constexpr intmax_t log(intmax_t number, intmax_t acc = 0) {
return number <= 1 ? acc : log(number / 2, acc + 1);
}
constexpr bool is_safe_multiple(std::intmax_t N1, std::intmax_t D1, std::intmax_t N2, std::intmax_t D2)
{
auto limit = log(std::numeric_traits<std::intmax_t>::max()) + log(std::gcd(N1, R2)) + log(std::gcd(N2, R1));
auto num = (log(N1) + log(N2)) < limit;
auto den = (log(R2) + log(R2)) < limit;
return num && den;
}
template <typename R1, typename R2>
using safe_ratio_multiply = typename safe_ratio_multiply_impl<R1, R2, is_safe_multiple(R1::num, R1::den, R2::num, R2::den)>::type;
【讨论】: