Re: C++0x static_assert(0, "") within a non-instantiated template
okay?
On 6/29/07 8:26 AM, in article
1183113163.342662.146830@n60g2000hse.googlegroups.com, "Vladimir Marko"
<swelef@post.sk> wrote:
On 29 Jun, 07:35, Greg Herlihy <gre...@pacbell.net> wrote:
On Jun 23, 9:54 am, nore...@this.is.invalid (Niels Dekker - no return
But unfortunately both BOOST_STATIC_ASSERT calls appear to be
ill-formed, even within an uninstantiated template, as Gennaro Prota
explained to me (by e-mail). Quoting the current Draft, 14.6, Name
resolution [temp.res]:
"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.
"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2284.pdf
The compiler does generate a valid specialization in this situation -
because if the "SpecializeMePlease" template definition were ill-forme=
d,
then no specialization would have been generated and the
BOOST_STATIC_ASSERT would never have been evaluated. In other words, i=
n
order for BOOST_STATIC_ASSERT(sizeof(T)==0) to be ill-formed, the
"SpecializeMePlease" specialization that led to its instantiation - mu=
st be
valid.
With all respect, this is nonsense. The compiler does not generate
a valid specialization, because none exists. The template definition
is ill-formed even without ever being instantiated (the quote provided
is very clear about it). And, finally, the compiler often needs to
instantiate a template specialization to find out _if_ it's ill-
formed,
making your last sentence rather ridiculous.
A static assert with a non-dependent expression (that evaluates to false)
does indeed render the template definition in which it appears, ill-forme=
d.
Moreover, the compiler is not obligated to diagnose this problem - unless
and until the template is instantiated.
Now, a static assert with a value-dependent expression (which subsequentl=
y
evaluates to false in a template specialization) renders the template
specialization - and only the specialization - ill-formed. Moreover an
ill-formed template specialization does not mean that the template
definition used to generate it was also ill-formed. On the contrary, beca=
use
only a well-formed template definition can generate a template
specialization successfully, the template definition must have been
well-formed in order to have generated an ill-formed specialization. Or t=
o
put it another way, the specialization could not be ill-formed - if it di=
d
not exist.
So the only question to resolve here is whether sizeof(T)==0 is a
value-dependent expression or not. Because if the expression is not value
dependent, then the static assert would be evaluated in the context of th=
e
template definition. Otherwise, if the expression is value-dependent, the=
n
its evaluation would be deferred until a template specialization.
According to the Standard, the expression sizeof(T) is value-dependent:
"Expressions of the following form are value-dependent if the
unary-expression is type-dependent or the type-id is dependent (even if
sizeof unary-expression and sizeof (type-id) are not type-dependent):
sizeof unary-expression
sizeof (type-id ) [=A714.6.2.3/2]
Moreover, since "a constant expression is value-dependent if any
subexpression is value-dependent", it follows that sizeof(T)==0 must
value-dependent because its subexpression, sizeof(T), is value-dependent.
While the compilers are likely to accept the code, the _language_
says the template definition is ill-formed. There is a workaround,
though:
template <typename>
struct always_false { static const bool value = false; };
template <typename T>
class specialize_me
{
static_assert(always_false<T>::value,"don't instantiate this
template");
};
Here, we could provide a specialization of always_false to make
it possible to generate a valid instantiation of specialize_me, thus
the definition of specialize_me can't be deemed ill-formed.
There is no material difference between the static_assert in the above
example and a static_assert(sizeof(T)==0). In both cases, the express=
ion
being asserted is value-dependent on a template type argument, T. Therefo=
re
in both cases the evaluation of the static_assert is deferred until the
specialize_me template is instantiated (if ever). So when either template=
is
instantiated: a well-formed template definition winds up generating a val=
id,
but ill-formed specialization.
Greg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]