Topic: 8.5/9
Author: gprenz@hotmail.com (Graeme Prentice)
Date: Thu, 22 Jul 2004 05:04:23 GMT Raw View
[ A slight correction to my other post (which will hopefully turn up
before this), where I said ... ]
<quote>
What do you mean by "functionally correct". If you mean that the
compiler should determine there's no data that needs initializing and no
members/bases with non-trivial default constructors so an implicit
do-nothing default constructor is sufficient then I would say that's an
unnecessary exception to the rule and such an object wouldn't need to be
const anyway. You don't indicate the storage duration (3.7) of the
objects which is also relevant IMO.
If a non POD object has non static storage duration then its reasonable
to require a const object to have either an initializer or a default
constructor because otherwise the memory for the object has an
indeterminate state and can't be changed (unless it's new'd into special
memory).
<end quote>
Since the implicitly defined default constructor still calls member and
base default constructors my comment above is slightly wrong, - an
implicit default constructor could be "functionally correct" as long as
any sub-object (including the object itself) with one or more non-static
data members has a user defined default constructor. This is still an
unnecessary exception to the rule in my opinion as it's trivial to add a
default constructor - unless for some reason you can't change the class
definition (don't know why that would be).
Graeme
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: gprenz@hotmail.com (Graeme Prentice)
Date: Thu, 22 Jul 2004 05:30:12 GMT Raw View
On Wed, 21 Jul 2004 14:33:16 GMT, David Abrahams wrote:
>
> "If no initializer is specified for an object, and the object is of
> (possibly cv-qualified) non-POD class type (or array thereof), the
> object shall be default-initialized; if the object is of
> const-qualified type, the underlying class type shall have a
> user-declared default constructor"
>
>Implication:
>
> struct foo {};
> struct bar : foo {};
> struct baz : foo { baz(){} };
>
> const bar x; // legal
> const baz y; // illegal
I think you mean
const bar x; // illegal
const baz y; // legal
>
>This one really took me by surprise. I had always assumed that if
>the implicitly-generated default ctor would be functionally correct,
>there was no need to define my own.
>
>Can anyone offer a rationale for this rule?
What do you mean by "functionally correct". If you mean that the
compiler should determine there's no data that needs initializing and no
members/bases with non-trivial default constructors so an implicit
do-nothing default constructor is sufficient then I would say that's an
unnecessary exception to the rule and such an object wouldn't need to be
const anyway. You don't indicate the storage duration (3.7) of the
objects which is also relevant IMO.
If a non POD object has non static storage duration then its reasonable
to require a const object to have either an initializer or a default
constructor because otherwise the memory for the object has an
indeterminate state and can't be changed (unless it's new'd into special
memory).
If the non POD object has static storage duration (i.e. is zero
initialized at startup) then the memory for the const object would have
a well defined state without an initializer or default constructor,
however the class may have members with non-trivial default constructors
so the compiler would have to detect that and allow only classes that
had all members and bases with trivial default constructors - which is
more trouble for the compiler than it's worth IMO and might cause
surprises when code got changed too.
I guess const POD in static memory are allowed no initializer for
compatibility with "C" and because with POD there are no non-trivial
default constructors involved, however I reported on this newsgroup on
26 May that GCC, Comeau and VC give errors for the following code (due
to the unclear text in 8.5/9 in my opinion) which I believe the standard
intended to be legal.
struct pod
{
int a;
int b;
unsigned char c;
//pod(){}
};
pod const abc1[30];
pod const abc2;
int const abc3;
int main()
{
}
The spurious errors for the above code reported by GCC required me to
workaround it at a cost, so in my post of 26 May I went to the trouble
of working out a rewording of 8.5/9 that I thought would be clearer as
follows, but because this seems like such a minor problem that hasn't
bothered anyone before now, I didn't post a defect report.
<proposed re-wording of 8.5/9>
If no initializer is specified for an object of type T then:
-- If T is a non-POD class type object (or array of), the object is
default initialized, and if the object is const-qualified, the
underlying class type shall have a user-declared default constructor.
-- If T is a POD object (possibly CV qualified) with static storage
duration (3.7.1) it is zero initialized at startup (8.5/6) and no
initializer is required.
-- If T is a POD object that does not have static storage duration, the
object and its subobjects, if any, have an indeterminate initial value
(90) and if the object or any of its subobjects are of const-qualified
type, the program is ill-formed.
Graeme
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: sean@f4.ca (Sean Kelly)
Date: Fri, 23 Jul 2004 20:55:51 GMT Raw View
gprenz@hotmail.com (Graeme Prentice) wrote in message news:<3o6uf01ejj7bgp5jv5l6l72u02q7k2jak7@4ax.com>...
>
> Since the implicitly defined default constructor still calls member and
> base default constructors my comment above is slightly wrong, - an
> implicit default constructor could be "functionally correct" as long as
> any sub-object (including the object itself) with one or more non-static
> data members has a user defined default constructor. This is still an
> unnecessary exception to the rule in my opinion as it's trivial to add a
> default constructor - unless for some reason you can't change the class
> definition (don't know why that would be).
But why make this a language requirement? It seems completely
reasonable to want to define a default constructed const object. Is
there any reason to require the user to explicitly define a
constructor in this case if the constructor would be empty?
Sean
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: gprenz@hotmail.com (Graeme Prentice)
Date: Sat, 24 Jul 2004 06:54:38 GMT Raw View
On Fri, 23 Jul 2004 20:55:51 GMT, Sean Kelly wrote:
>gprenz@hotmail.com (Graeme Prentice) wrote in message news:<3o6uf01ejj7bgp5jv5l6l72u02q7k2jak7@4ax.com>...
>>
>> Since the implicitly defined default constructor still calls member and
>> base default constructors my comment above is slightly wrong, - an
>> implicit default constructor could be "functionally correct" as long as
>> any sub-object (including the object itself) with one or more non-static
>> data members has a user defined default constructor. This is still an
>> unnecessary exception to the rule in my opinion as it's trivial to add a
>> default constructor - unless for some reason you can't change the class
>> definition (don't know why that would be).
>
>But why make this a language requirement? It seems completely
>reasonable to want to define a default constructed const object. Is
>there any reason to require the user to explicitly define a
>constructor in this case if the constructor would be empty?
Do you mean that it's reasonable to want to define a const object that
has no data - (why would you want to do that?) or do you mean that the
compiler should try to work out if the resulting object would have no
uninitialized const data anywhere and provide an implicit default
constructor if so?
I guess in general, it's an attempt to warn the programmer that there
might be some uninitialized const data and catching errors wins the day
over a redundant user defined default constructor.
How much the warning is worth I don't know ( I suspect not much) and how
easy it would be for the compiler to determine that the user defined
default constructor would be empty I also don't know but I believe that
it would be a waste of space in the C++ standard to try to define when
you do and don't need a user defined default constructor for a const
object. I would probably favour taking out the requirement for a
default constructor (especially if the object is in static memory) and
let the programmer take responsibility for what happens if she makes a
const object. If she makes it const she's saying "this object has some
stuff I want to read but not write" and should know what that is at the
declaration of that object. You can read uninitialized data in a non
const object and never know ...
Regarding my previous comment about it being trivial to add a default
constructor unless you can't change the class definition - it could
well be that you can't or don't want to change the class definition e.g.
if it was part of a library or third party code, but my guess is that if
it was meaningful to have a const object of such a class, then the
library code would have already allowed for it and provided a default
constructor. If not, there's a chance you could inherit to get round
it.
The kind of class we're talking about here is a non-POD with no
constructors (which just happens to be the type of class affected by the
TC1 value initialization change), so if you take a simple case of Dave
Abrahams original example but add a data member (coz why else would you
need it to be const other than perhaps some rare obscure cases)
struct foo { int x; };
struct bar : foo {};
struct baz : foo { baz(){} };
A const bar object is obviously an error in 99%+ of cases unless it's in
static storage.
But I can write this and get no warning that non POD b2 is uninitialized
struct foo2
{ bar b2;
foo2(){}
};
const foo2 f2;
so whether the requirement for a user defined default constructor is
good or bad (apart from surprising people, it's no big deal either way
AFAICS), it's better than the compiler and the C++ standard trying to
distinguish between cases that may or may not be errors.
Graeme
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Wed, 21 Jul 2004 14:33:16 GMT Raw View
"If no initializer is specified for an object, and the object is of
(possibly cv-qualified) non-POD class type (or array thereof), the
object shall be default-initialized; if the object is of
const-qualified type, the underlying class type shall have a
user-declared default constructor"
Implication:
struct foo {};
struct bar : foo {};
struct baz : foo { baz(){} };
const bar x; // legal
const baz y; // illegal
This one really took me by surprise. I had always assumed that if
the implicitly-generated default ctor would be functionally correct,
there was no need to define my own.
Can anyone offer a rationale for this rule?
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]