Hi all,
Note - this is with respect to C++ 03.
*Test code:*
*template <int> struct A {};int const i = {42};typedef A<i> Ai;*
Short, snarky answer - you can’t bracket-initialize a variable in c++03
You can in a few cases: specifically, if the type is an aggregate or a
scalar type. In the latter case,
T x = { a };
is equivalent to
T x = a;
(See C++03 [dcl.init](8.5)/13.)
int const i = {42};
For non-type template argument, standard (C++ 03) says that:
*14.3.2 / 1*
*A template-argument for a non-type, non-template template-parameter shall
be one of:*
- *an integral constant-expression of integral or enumeration type; or
......*
For the test code above, the statement '*typedef A<i> Ai*', should the
compiler
check the rhs (rvalue) of variable 'i' to determine if it is a constant or
not?
Yes. For 'i' to be an integral constant-expression, it can only mention
"const variables [...] of integral or enumeration types initialized with
constant expressions" (C++03 [expr.const](5.19)/1). So the compiler is
required to check whether 'i' is indeed initialized by a constant
expression.
Shouldnt it just check the type of i (which is declared as const)?
Whether 'i' evaluates to constant (at compile time) or not should be the
responsibility of compiler
while processing statement '*int const i = {42}*' and not '*typedef A<i>
Ai' ? Isnt it?*
Another analogy:
For arrays, the size of the array needs to be a compile time constant. So,
the following code :
*int const x = 42;*
*int z[x];*
For the statement *'int z[x]'*, will the compiler evaluate the rhs of
*'x'* to check if it evaluates to constant at runtime
or will it just see that '*x*' is of 'integer const' type and hence there
is no problem with the array declaration?
Whether '*x*' evaluates to constant should be the responsibility of
compiler while processing statement '*int const x=42*'
and not while processing '*int z[x]*' ?
Should this analogy be applicable to non-type template argument?
According to the C++ standard, the two cases are exactly the same. However,
to support code relying on GCC extensions, we allow any constant-foldable
expression as an array bound, whereas we require a constant-expression as a
template argument. Use -pedantic-errors to enable Clang's
strictly-conforming mode, where we (incorrectly) reject both cases.
The bug is that CheckICE in lib/AST/ExprConstant.cpp (or
maybe VarDecl::checkInitIsICE) doesn't handle the case of an InitListExpr
being used to initialize a scalar.
Please throw some light on this, am I missing any particular case?
My understanding (which may be flawed) is that the compiler needs to see
both:
* That the compiler needs to be able to determine that the value it needs
is const
* That the compiler can see what the value actually is, so that it can
allocate space for the array, or instantiate the template.
So, this would not work:
extern const int i;
template <int> struct A {};
typedef A<i> Ai;
Right.