[Bug c++/53638] static_assert handling behavior ignores template specializations

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Mon Jun 11 21:14:00 GMT 2012


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53638

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> 2012-06-11 21:14:25 UTC ---
(In reply to comment #0)
> It is my opinion that this is not true.

It is true.

>  It is possible that the template might
> have valid specializations that occur later on in the compilation unit, making
> it impossible to determine whether or not it is possible to construct an
> instantiation of the template when parsing.

No it isn't. You can generate valid instantiations from a *different* template
definition, but the wording is in terms of template definitions, not templates.


> The relevant part of the standard says this " Refer to 14.6p8 in the spec
> 
> If no valid specialization can be generated for a template definition, and that
> template is not instantiated, the template definition is ill-formed, no
> diagnostic required.
> "

It specifically says "for a definition". The primary definition of a template
is a definition, an explicit specialization provides a different definition. 
If a valid instantiation can be generated from the second definition that
doesn't change the fact that if no valid instantiation can be generated for the
primary definition then that primary definition is ill-formed.


> This seems at first to imply that the current behavior is legal.  However, the
> current behavior evaluates the static_assert and emits a message EVEN if valid
> specializations CAN still be generated for a template definition.
> 
> Consider this code:
> 
> template<bool a>
> struct s {
>     static_assert(0, "uhoh");
> };
> 
> template<>
> struct s<false> {
> 
> };
> 
> s< false > q;  
> 
> This should compile, because s<false> is a valid specialization of s, meaning
> that s<a> does not get instantiated.

No, the primary template is a template definition but no valid specialization
can be generated from it. The explicit specialization is a second definition,
its existence doesn't change the fact the primary definition cannot ever be
used (also the explicit specialization hasn't even been seen when the primary
definition is first parsed.)

>  However, on gcc 4.5.1 and gcc 4.7, we get
> 
> prog.cpp:3:5: error: static assertion failed: "uhoh"

And also on clang++ and EDG.

> Strangely, because of this behavior, we can 'fix' it by making the constant
> expression dependent on a, even if we know it will always be false
> 
> template<bool a>
> struct s {
>     static_assert(a!=a, "uhoh" );
> };

That is a bit strange at first sight, but actually that doesn't fix anything,
that definition is still ill-formed because no valid instantiation can be
generated from it.  It would be conforming for a compiler to reject that
program, but it's not required to (it's "ill-formed, no diagnostic required.")

The solution is to not write it like that.
A more sensible definition would be:

template<bool a>
struct s {
    static_assert(!a, "uhoh");
};

Or even just 

template<bool a> struct s;

(Though the static assertion does give the option of a nicer message.)

> template<>
> struct s<false> {
> 
> };
> 
> Compiles. 
> 
> The current behavior of GCC in this case MAY be conformant with spec, but it

It definitely is. Read 14.6p8 again.  It doesn't matter if the template is
never instantiated, it's ill-formed.

> seems to go against the intent of the spec even if it doesn't go against the
> letter. 

I don't see how it goes against the intent -- the standard clearly says a
template definition from which no valid specialisation can be generated is
ill-formed.

Your primary template is such a definition. So it's ill-formed.

> It also makes it difficult to use static_assert in certain
> metaprogramming applications(like the example above, which could be used to
> evaluate if a metafunction returned true).

So make it dependent, or leave the primary template undefined.

The alternative is to change three major compilers to accommodate a highly
questionable style of metaprogramming that the standard says is ill-formed.
Don't do it.

> Also, as bug 52809 demonstrates, it
> is confusing to users.

It doesn't demonstrate that at all, it just asserts it.



More information about the Gcc-bugs mailing list