template<typename T, typename U = void>
struct S { /* static_assert(0, "type unsupported"); */ };
template<typename T>
struct S<T, typename std::enable_if<std::is_integral<T>::value, void>::type> {
void foo() {}
};
...
S<int> i;
i.foo();
S<double> d;
// d.foo();
I would be expecting that the "master template" would never be instantiated for the case of int
, but if I uncomment the static_assert
, the S<int>
instantiation will fail. Even a lone typedef S<int> Si;
would fail to compile. (GCC 4.9.2 Cygwin)
What I aimed to achieve is not for S<double>
to fail at the foo()
call, but at the instantiation of the template itself, and that with a meaningful error message. I'm aware I can do something like typename T::nonexistent_type t;
in the master template which will prevent the template for compiling, but that'd be inferior to a static_assert
message. (Note: putting the static_assert
within a function definition in the master template still fails compilation for S<int>
)
Why does the static_assert
fail even though that template is not instantiated? Is this mandated (or perhaps "unspecified") by the standard? Is there a way to fail with a static_assert
the way I wish to?
The expression in the static_assert
must be dependent on a template parameter if you wish it to be instantiation-time only. This is guaranteed by Standard- the implementation may (but has no obligation to) check static_assertion
s in templates that are not dependent on any template parameter.
Your code is a strange roundabout way of doing something like
template<typename T> struct S {
static_assert(std::is_integral<T>::value, "type unsupported");
void foo() {}
};
This clearly communicates to the compiler the dependency between the expression and the template parameter, and is far clearer and easier to read as well. I actually couldn't quite figure out if you wanted compilation to fail for integral types or for non-integral types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With