我制作了一些模板,旨在
- (1)测试数字是否可以相加而不溢出,
- (2)添加数字,如果溢出则失败。
test_sum
里面的(1)static_assert
编译通过了,所以我猜是的constexpr
。
为了避免重复计算,我尝试将断言直接放在计算和的 (2) 函数中。然而,在下面的所有版本中,无论条件如何,断言总是失败。有什么办法可以解决这个问题吗?
#include <limits>
#include <stdexcept>
#include <type_traits>
template<typename T>
constexpr bool add(T& a, T b)
{
static_assert(std::is_integral<T>::value, "Only integral types are supported");
if ((b > 0) && (a > std::numeric_limits<T>::max() - b))
return false;
if ((b < 0) && (a < std::numeric_limits<T>::min() - b))
return false;
a += b;
return true;
}
//
template<typename T>
constexpr bool sum_impl(T& result)
{
return true;
}
template<typename T, typename... Rest>
constexpr bool sum_impl(T& result, T value, Rest... rest)
{
if (!add(result, value))
return false;
return sum_impl(result, rest...);
}
//
template<typename T, typename... Rest>
constexpr bool test_sum(T value, Rest... rest) // (1)
{
return sum_impl(value, rest...);
}
template<typename T, typename... Rest>
T sum(T value, Rest... rest) // (2) regular
{
if (!sum_impl(value, rest...))
throw std::overflow_error("Overflow in checked::sum");
return value;
}
template<typename T, typename... Rest>
constexpr T sum_cexpr(T value, Rest... rest) // (2) constexpr
{
// if (!sum_impl(value, rest...))
// static_assert(false, "Overflow"); // fail
// static_assert(sum_impl(value, rest...), "Overflow"); // fail
// if (!sum_impl(value, rest...))
// delegated_assert<false>(); // fail
return value;
}
template<bool B>
constexpr void delegated_assert()
{
if constexpr (!B)
static_assert(B);
}
//////
int main()
{
static_assert(test_sum(1, 2)); // (1) works
constexpr int a = sum_cexpr(10, 20, 30); // fails to compile
return 0;
}