I made some templates which are supposed to
The (1) test_sum
inside static_assert
compiles, so I guess it is constexpr
.
I wanted to avoid duplicating the math, so I tried to put the assert directly inside the (2) function that calculates the sum.
However, the assert always fails, no matter the condition, in all the versions below. Can this be solved in any way?
#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;
}
static_assert(sum_impl(value, rest...), "Overflow");
This cannot possibly work because value
and rest
aren't constant expressions.
Just because this static_assert
is inside a constexpr
function doesn't mean that you could read out their values within static_assert
.
See also Can't use function parameter of a constexpr function in a constant expression
static_assert(false, "Overflow");
and delegated_assert<false>();
are obviously going to fail as well. static_assert
ions are evaluated at compile time, and it is irrelevant whether you put them into an if
statement.
You can only have such "conditional static_assert
s in an if constexpr
statement, but that wouldn't work for the same reason that the aforementioned static_assert
always fails.
In general, the static_assert
s seem unnecessary here.
If an overflow is detected, an exception will be thrown, and
constexpr int a = sum(10, 20, 30);
... won't compile.