There is nothing in the language that requires compilation to abort immediately, so anything you get that directly answers your question will necessarily be implementation-specific and won't avoid the instantiations on other implementations. What I think would be better is to rework your code in such a way that it doesn't have any way to continue with the instantiations. One possible way to do this is with std::enable_if
:
#include <iostream>
#include <type_traits>
template <int x, typename = typename std::enable_if<x >= 0>::type>
struct SUM_impl
{
enum {VALUE = x + SUM_impl<x-1>::VALUE};
};
template<>
struct SUM_impl<0>
{
enum {VALUE = 0};
};
template <int x>
struct SUM
{
static_assert(x >= 0, "X must be greater or equal to 0");
enum {VALUE = SUM_impl<x>::VALUE};
};
int main()
{
std::cout << SUM<-1>::VALUE << std::endl;
return 0;
}
This way, the static_assert
in SUM
prints out a user-friendly message. The enable_if
in SUM_impl
forcibly rejects anything where x < 0
, before the template would be instantiated, and if the template doesn't get instantiated, it cannot be instantiated recursively either.
I initially made SUM
derive from SUM_impl
, but not doing so (and copying its value) provides better diagnostics.