Conditionally static_assert if function is called constexpr
In your particular case you can just leave assert - it will prevent compiling when the condition is wrong since the assert handler is non-constexpr:
#include <cassert>
struct F {
constexpr F(int v) {
assert(v >0);
}
};
// ...
constexpr F f1{0}; // doesn't compile in debug
constexpr F f2{1}; // compiles
However this won't trigger the compile-time error in release. It can be solved by making your own assert and adding call to some non-constepxr function:
#include <cassert>
// some non-constexpr function
void AssertConditionFailed()
{
}
#define ASSERT_WIH_COMPILE_TIME_CHECK(...) \
assert(__VA_ARGS__); \
if (!(__VA_ARGS__)) \
{ \
AssertConditionFailed(); \
}\
struct F {
constexpr F(int v) {
ASSERT_WIH_COMPILE_TIME_CHECK(v >0);
}
};
// ...
constexpr F f1{0}; // doesn't compile
constexpr F f2{1}; // compiles
Not in such a direct way, because static_assert
will simply not be allowed there, and similarly trying to use v
as a template argument will fail so no use of enable_if
type solution.
For the purposes of errors, if a constexpr results in an exception, you will get a compile error.
You could use a macro such as assert
(allowed since C++14) allowing it to be optimised out in release builds and keeping your original debug runtime behaviour.
constexpr int foo(int v)
{
if (v < 0) throw std::invalid_argument("invalid v");
return v * 2;
}
int main() {
int a = -1;
int a2 = foo(a); // Not evaluated at compile time
constexpr int b = foo(2);
constexpr int c = foo(-1); // ERROR
}