[cfe-dev] <PR 18283> C++ 03 - Need clarification regarding non-type template argument

Richard Smith richard at metafoo.co.uk
Wed Jan 22 11:42:27 PST 2014

On Wed, Jan 22, 2014 at 11:22 AM, Marshall Clow <mclow.lists at gmail.com>wrote:

> On Jan 21, 2014, at 5:59 AM, Rahul Jain <rahul1.jain at samsung.com> wrote:
> 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

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;

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140122/e46d8ab2/attachment.html>

More information about the cfe-dev mailing list