Static_assert with partial template specialization

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 expect that the "master template" would never be created for the int case, but if I uncomment static_assert , creating an instance of S<int> will fail. Even a single typedef S<int> Si; will not be able to compile. (GCC 4.9.2 Cygwin)

What I was striving for was not that S<double> failed when calling foo() , but when creating the template itself, as well as with a significant error message. I know that I can do something like typename T::nonexistent_type t; in the main template, which will prevent the template from being created, but it will be worse than the static_assert message. (Note: placing static_assert in the function definition in the wizard template is still not running for S<int> )

Why is static_assert executed even if this template is not created? Is this a mandatory (or possibly "unspecified") standard? Is there a way to fail with static_assert as I want?

+5
source share
1 answer

The expression in static_assert should depend on the template parameter if you want it to be only an instance instance. This is guaranteed by the standard - an implementation can (but is not required to) check static_assertion in templates that are independent of any template parameter.

Your code is a weird roundabout way to do something like

 template<typename T> struct S { static_assert(std::is_integral<T>::value, "type unsupported"); void foo() {} }; 

This clearly tells the compiler the relationship between the expression and the template parameter and is much clearer and easier to read. Actually, I could not understand if you want compilation for integral types or for non-integer types.

+7
source

All Articles