Topic: Why Does an Object of an Empty Classs Require a User-declared Constructor?
Author: gennaro_prota@yahoo.com (Gennaro Prota)
Date: Thu, 28 Sep 2006 14:41:59 GMT Raw View
On Wed, 27 Sep 2006 09:38:30 CST, "kanze" <kanze@gabi-soft.fr> wrote:
>> > const Sign SignFunction; // Error: uninitialized const object
>
>> >Instead, Sign must declare a default constructor:
>
>> It doesn't need to. You may just provide an initializer for the const
>> instance:
>
>> const Sign SignFunction = {};
>
>But you've missed his point: you need a user specified
>initialization in order to initialize nothing.
No no, I didn't miss it :-) I was just replying to the "you must
declare a default constructor part". I agree that this should be fixed
(though admittedly it's not a big problem), and from what I remember,
the "why should I specify an initialization to initialize nothing" was
exactly the point raised by Scott Meyers. In Scott's code, by the way,
the class was unnamed so defining a user constructor wasn't quite a
choice :-)
--
Gennaro Prota
---
[ 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 ]
Author: "kanze" <kanze@gabi-soft.fr>
Date: Thu, 28 Sep 2006 10:03:57 CST Raw View
SuperKoko wrote:
> kanze wrote:
> > -- Or more simply, drop the above clause completely. After
> > all, if the intent is mainly to require that C style const
> > objects be initialized, C doesn't have the rule,
> C does require initializers for const objects! and it is,
Where. I couldn't find it in my copy of C99. And gcc doesn't
require it.
> > in fact, not a rare practice to declare such a const object
> > in C, to have an initialize for auto objects, e.g.:
> > struct S { int i ; int j ; } ;
> > S const sInit ;
> > void
> > f()
> > {
> > S someS = sInit ;
> > // ...
> > }
> The code snippet below is flawed because "S const sInit;" is a
> declaration of an external const object while it's an
> ill-formed definition in C++ (because const variables with
> namespace scope are "static" by default in C++ but not in C).
It's illegal in C++, because there is no initializer for sInit.
It is quite common practice in C. Except, of course, that I
miscopied from my C++ source, rather than the C source; in C, I
would have to write:
struct S const sInit ;
It's true that there are several differences here between C and
C++: to begin with, as you say, in C++, the name sInit has
internal linkage, where as in C, it has external. And while it
is a definition in both languages (the const plays no role
here), the way C and C++ define external linkage is slightly
different.
> Replace "S const sInit;" with "static S const sInit;" and
> you'll see.
See what? It doesn't change anything fundamental.
> Or simply compile your code and have a look at
> "undefined symbol" linker errors.
There aren't any. There's no doubt that what I have written is
a definition, and is sufficient. (I might add that gcc accepts
it---that's the only C compiler I currently have access to.)
> > The idea being to simulate for auto objects the same
> > initialization we get for static objects.
> But in that case, the correct *definition* for sInit is:
> struct S const sInit={0};
That will also work, but it wasn't the idiomatic form when I was
using C. (Admittedly, we didn't have the const back then,
either, so it was simply "struct S sInit;". But adding the
const, now that it has been added to C, is a logical
progression, and it works fine with gcc.)
> Seriously, I don't see any benefit (e.g. it is not more
> convenient nor more simple) in specifying that an empty class
> can be initialized in such way.
Supporting existing practice in C. Personally, it doesn't make
much difference to me today, because about the only time I use
an aggregate class is because I want to be able to use the {...}
initialization. If we want to pretend that C++ POD are in some
way compatible with C objects, then not having the rule makes
sense. But I'll admit that's the only justification for using
it rather than my first suggestion (only requiring
initialization if there is one or more non-static data members).
> It breaks the easy to remember (but not exhaustive) rule that
> const aggregates require aggregate initializers.
Yes, but...
When writing C++ code, you don't have aggragate types except in
order to use the {...} initialization; the simply problem
doesn't occur. So the rule doesn't jurt, but it isn't
necessary.
When trying to compile C code with a C++ compiler, on the other
hand, it makes one less thing you might have to change.
--
James Kanze GABI Software
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ 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 ]
Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Tue, 26 Sep 2006 09:39:04 CST Raw View
Is there a particular reason why C++ requires that the empty class of a
const object have a user-declared, default constructor? For example,
this code will not compile:
struct Sign
{
int operator()( int i ) const
{
return -(i < 0) + (i > 0);
}
};
const Sign SignFunction; // Error: uninitialized const object
Instead, Sign must declare a default constructor:
struct Sign
{
Sign() {}
int operator()( int i ) const
{
return -(i < 0) + (i > 0);
}
};
Now, (according to a rather informal definition) a function object that
maintains no state should not declare a constructor. Especially one
whose declaration makes absolutely no difference to the program. In
contrast, declaring a const function object variable does make sense.
In fact it is not possible to define a function object in a shared
header file unless it is declared const. A non-const object definition
in a shared header file would violate the One Definition Rule (ODR).
And the gist of these observations is simply that the error illustrated
in the sample code above is not contrived, or even all that unlikely,
in light of these factors.
Now my usual response to an error compiling is to fix the error. But
there are two problems that I have with this particular compiler error
- first I don't see any error. Specifically, I don't see anything in
Sign that needs to be initialized. So I have trouble identifying
exactly what unitialized object the compiler is complaining about.
Almost as baffling to me, is the whereabouts of the
implictly-generated, default constructor that the compiiler is supposed
to generate - the one used to construct non-const Sign objects. Did it
disappear? As far as I can tell, the compiler-generated should still
exist - but for some inscrutable reason the Standard has its
invisibility prevent it from being called for a non-const instance.
The other issue that I have is that I can't that the change that fixes
this problem is any kind of change at all. How does the user declaring
the same constructor that would have been generated had the constructor
not been declared - do anything to fix this problem? As far as i can
tell, nothing should have been affected by such a change, yet somehow
the problem gets fixed.
I guess I have a third problem as well. And that is a problem of
perception: C++ seems to me to to be unique among computing languages.
In particular, it is the only language in which successfully compiling
a program may require that the programmer make a pointless change to
fix a problem that did not exist in the first place.
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 ]
Author: gennaro_prota@yahoo.com (Gennaro Prota)
Date: Tue, 26 Sep 2006 15:24:30 GMT Raw View
On Tue, 26 Sep 2006 09:39:04 CST, "Greg Herlihy" <greghe@pacbell.net>
wrote:
>Is there a particular reason why C++ requires that the empty class of a
>const object have a user-declared, default constructor? For example,
>this code will not compile:
>
> struct Sign
> {
> int operator()( int i ) const
> {
> return -(i < 0) + (i > 0);
> }
> };
>
> const Sign SignFunction; // Error: uninitialized const object
>
>Instead, Sign must declare a default constructor:
It doesn't need to. You may just provide an initializer for the const
instance:
const Sign SignFunction = {};
I guess this problem was "popularized" by Scott Meyer's null (same
problem there: either you gave it a default constructor or provided an
initializer)
--
Gennaro Prota
---
[ 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 ]
Author: "kanze" <kanze@gabi-soft.fr>
Date: Wed, 27 Sep 2006 09:38:30 CST Raw View
Gennaro Prota wrote:
> On Tue, 26 Sep 2006 09:39:04 CST, "Greg Herlihy" <greghe@pacbell.net>
> wrote:
> >Is there a particular reason why C++ requires that the empty
> >class of a const object have a user-declared, default
> >constructor? For example, this code will not compile:
> > struct Sign
> > {
> > int operator()( int i ) const
> > {
> > return -(i < 0) + (i > 0);
> > }
> > };
> > const Sign SignFunction; // Error: uninitialized const object
> >Instead, Sign must declare a default constructor:
> It doesn't need to. You may just provide an initializer for the const
> instance:
> const Sign SignFunction = {};
But you've missed his point: you need a user specified
initialization in order to initialize nothing.
I suspect that when the rule was written, the authors intent was
to prevent you from declaring uninitialized C-style structs. If
I have a typical C style struct, I have to provide
initialization (using the braces) if the object is const. (This
would explain, for example, why the compiler doesn't take into
account the compiler generated default constructor.) If I
provide an explicit constructor, of course, the langage supposes
that that constructor does the right thing, and that there is no
problem.
I agree with Greg that this should probably be fixed. I can see
two simple fixes:
-- In 8.5/9, change "if the object is of const-qualified type,
the underlying class type shall have a user-declared default
constructor." to "if the object is of const-qualified type,
and contains one or more non-static data members, the
underlying class type shall have a user-declared default
constructor."
-- Or more simply, drop the above clause completely. After
all, if the intent is mainly to require that C style const
objects be initialized, C doesn't have the rule, and it is,
in fact, not a rare practice to declare such a const object
in C, to have an initialize for auto objects, e.g.:
struct S { int i ; int j ; } ;
S const sInit ;
void
f()
{
S someS = sInit ;
// ...
}
The idea being to simulate for auto objects the same
initialization we get for static objects.
--
James Kanze GABI Software
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ 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 ]
Author: "SuperKoko" <tabkannaz@yahoo.fr>
Date: Wed, 27 Sep 2006 12:15:47 CST Raw View
kanze wrote:
> -- Or more simply, drop the above clause completely. After
> all, if the intent is mainly to require that C style const
> objects be initialized, C doesn't have the rule,
C does require initializers for const objects! and it is,
> in fact, not a rare practice to declare such a const object
> in C, to have an initialize for auto objects, e.g.:
> struct S { int i ; int j ; } ;
> S const sInit ;
>
> void
> f()
> {
> S someS = sInit ;
> // ...
> }
The code snippet below is flawed because "S const sInit;" is a
declaration of an external const object while it's an ill-formed
definition in C++ (because const variables with namespace scope are
"static" by default in C++ but not in C).
Replace "S const sInit;" with "static S const sInit;" and you'll see.
Or simply compile your code and have a look at "undefined symbol"
linker errors.
> The idea being to simulate for auto objects the same
> initialization we get for static objects.
>
But in that case, the correct *definition* for sInit is:
struct S const sInit={0};
Seriously, I don't see any benefit (e.g. it is not more convenient nor
more simple) in specifying that an empty class can be initialized in
such way.
It breaks the easy to remember (but not exhaustive) rule that const
aggregates require aggregate initializers.
---
[ 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 ]