Member initialization of arrays of constants
llewelly@dbritsch.dsl.xmission.com
llewelly@dbritsch.dsl.xmission.com
Tue Jul 25 10:52:00 GMT 2000
I think we should move this discussion to comp.std.c++ .
> On Sun, 23 Jul 2000 llewelly@dbritsch.dsl.xmission.com wrote:
>
> >There is nothing in 8.5.1 [dcl.init.aggr] that disallows initializing
> > a member array of constant type with a brace-enclosed initializer
> > list.
>
> Then it seems, I've found a bug in both Borland C++ 5.5 and Visual C++
> 5.0. They throw errors upon compilation of my code examples and
> further related tests.
>
> In case of brace-enclosed copy-initialization (_dcl.init.aggr_) of an
> array of constant chars, BC says:
>
> struct C
> {
> const char c[4];
> };
>
> Error: Constant member 'C::A::c' in class without constructors
I cannot find wording in the standard that disallows const members
from classes without constructors.
(Nor have I ever found a C++ compiler that did not have a multitude of
bugs.)
>
> >In both of your examples, A is an aggregate, and can therefor be
> > initialized with a brace-enclosed initializer list. (See 8.5.1)
>
> How's that possible, considering the extended example of a class with
> default constructor and, for instance, a non-static member constant of
> aggregate type?
It is possible because 8.5.1 allows it.
>
> If you say, it _can_ be initialized, shouldn't the following code be
> ill-formed then? Uninitialized const-qualified types, according to
> 12.6.1, 4:
>
> #include <iostream.h>
> #include <iomanip.h>
>
> struct A
> {
> const char c[4];
> const j;
I presume 'const j' was intended to be 'const int j' .
> int i;
>
> A()
> {
> i = 42;
> }
I do think 12.6.1/4 makes this constructor ill-formed, however, your
previous examples did not contain user-defined constructors, and
were aggregates according to 8.5.1; this class is not.
(gcc 2.95.2, and 2.96 20000626 both compile it without errors, and
that (I belive) *is* a bug, but it is different from your earlier
examples.)
> };
>
> void f()
> {
> A a;
> cout << a.i << endl; // okay, a.i is initialized
> cout << a.j << endl; // oops?
> cout << a.c << endl; // oops?
>
> const A b = { "foo", 1, 2 }; // error
> // b' must be initialized by constructor, not by `{...}'
> };
>
> >The fact that there are const-qualified types in involved does not
> > matter in either of your examples; const qualifed types can be
> > initialized the same way.
>
> I'd be forced to make each array of constants static. Else I could not
> perform copy-initialization.
>
> 9.2, 4
>
> A member-declarator can contain a constant-initializer only if
> it declares a static member (_class.static_) of integral or
> enumeration type, see _class.static.data_.
A member-declarator is a declaration of a member inside a class
declaration.
In your 'Example 2', the initialization was not in the class
declaration, and so I do not see how 9.2/4 applies.
>
> If you mean, that the brace-enclosed initializer-list is a special
> case which can only initialize static constant member aggregates, this
> would make sense.
hm? No, I did not mean that at all. Given:
struct A
{
const char a[4];
int i;
};
A has no user-declared constructors, no private or protected nonstatic
data members, no base classes, and no virtual functions. [8.5.1/1]
So A is an aggregate type; any instance of A may be initialized by
brace enclosed initialization.
An instance of A which is a static const member of a non-aggregate
type is still itself an aggregate, and can be initialized by
brace enclosed initialization;
class C
{
static const A a;
};
const A C::a = { 'T','E','S','T', 2 };
is well-formed. This does not require special cases; it is a
natural result of combing the rules on how static members are
initialized (9.4.2), with the rules for initializing aggregates
(8.5.1).
>
> >(If const-qualifed members could not be initialized, there would no
> > use for them.)
At the time I made this comment, I was thinking of static const
members.
>
> Well, const-qualified members can be initialized via the ctor's
> mem-initializer list.
static data members, const or not, cannot be initialized via the
ctor's mem-initializer list, as they are per class and not per
instance.
> But what about member arrays of const-qualified
> basic types?
>
> >(The rule you are probably thinking of is probably based on 12.6.2/4,
> > which does not apply to static data members, or to initialization of an
> > aggregate via a brace-enclosed intializer list.)
>
> Yes. Whenever I add a constructor, I can forget about using the
> brace-enclosed initializer-list. Hmmm...
That is what 8.5.1/1 says.
[snip]
More information about the Gcc-bugs
mailing list