Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 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?

like image 695
Irfy Avatar asked May 17 '15 11:05

Irfy


1 Answers

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_assertions 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.

like image 147
Puppy Avatar answered Oct 15 '22 13:10

Puppy