Can I fail compilation based on constexpr if?

113 Views Asked by At

Is there a workaround to do something like this?

if constexpr (std::floating_point<T>) {}
else if constexpr (std::integral<T>) {}
...
else static_failure("Feature expansion needed");

because if I replace static_failure with static_assert, it needs the replication of all the above conditions (they are many and complicated) and it becomes ugly.

// It does not work properly: always fail
else static_assert(false, "Feature expansion needed");
// works fine, but it is ugly
else static_assert(std::floating_point<T> || std::integral<T> || ... || ... || ..., "Feature expansion needed");

I do not prefer a runtime behavior like:

throw "Feature expansion needed";
3

There are 3 best solutions below

1
Jarod42 On BEST ANSWER

In C++23, you might use static_assert(false); in non-instantiated context. Before, it would be ill-formed NDR, but most compiler do diagnostic on that.

if constexpr (std::floating_point<T>) { /*...*/ }
else if constexpr (std::integral<T>) { /*...*/ }
/*...*/
else static_assert(false, "Feature expansion needed");

Before C++23, you have to cheat, common legal way is with always_false:

template <typename T>
struct always_false : std::false_type {};

and then

if constexpr (std::floating_point<T>) { /*...*/ }
else if constexpr (std::integral<T>) { /*...*/ }
/*...*/
else static_assert(always_false{}, "Feature expansion needed");
1
Salgar On

Yes, you just need the static assert to be dependant on T and always be false like this:

if constexpr (std::is_integral_v<T>) {}
else
    static_assert(sizeof(T) < 0, "Only works for integral T");

https://godbolt.org/z/Yhesd58rK

0
Red.Wave On

replace your last if constexpr with static_assert.

Instead of:

else if constexpr (last_case)
     //Do last case
else
     static_failure("prompt");

Do this:

else {
     static_assert(last_case,"prompt");
     //Do last case
};

Some proposals are made to legalize static_assert(false, "prompt");, but it is not yet part of std.