Topic: Defect Report: ill-formed example in [expr.mptr.oper]/5


Author: Giovanni Bajo <noway@sorry.com>
Date: Tue, 4 Jan 2005 05:26:08 +0000 (UTC)
Raw View
Hello,

[expr.mptr.oper]/5 contains an ill-formed example:

------------------------------------------
[1]     struct S {
[2]             mutable int i;
[3]     };
[4]     const S cs;
[5]     int S::* pm = &S::i;            // pm refers to mutable member S::i
[6]     cs.*pm = 88;                    // ill-formed: cs is a const object
------------------------------------------

The comments come from the original text, but there is an additional, unwanted
problem at line 4: the const object is not explicitally initialized, and class
S does not have an explicit default construction. This makes the code
ill-formed as per [dcl.init]/9.
--
Giovanni Bajo



[ 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: Graeme Prentice <gprenz@hotmail.com>
Date: Wed, 5 Jan 2005 08:29:45 CST
Raw View
On Tue, 4 Jan 2005 05:26:08 +0000 (UTC), Giovanni Bajo wrote:

>
>Hello,
>
>[expr.mptr.oper]/5 contains an ill-formed example:
>
>------------------------------------------
>[1]     struct S {
>[2]             mutable int i;
>[3]     };
>[4]     const S cs;
>[5]     int S::* pm = &S::i;            // pm refers to mutable member S::i
>[6]     cs.*pm = 88;                    // ill-formed: cs is a const object
>------------------------------------------
>
>The comments come from the original text, but there is an additional, unwanted
>problem at line 4: the const object is not explicitally initialized, and class
>S does not have an explicit default construction. This makes the code
>ill-formed as per [dcl.init]/9.


Hi Giovanni

The wording in 8.5/9 is ambiguous and I said so here
http://makeashorterlink.com/?I17A2192A
(full text copied below)

and I wrote the following as a suggested amendment  - it would make the
example above legal if cs has static storage duration because S is a POD
(an odd POD).


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.


I didn't post this as a defect report though.

Graeme



>From comp.std.c++ 26 May 2004


Is this code well formed?

struct pod
{
  int a;
  int b;
  unsigned char c;
  //pod(){}
};

pod const abc1[30];
pod const abc2;
int const abc3;

int main()
{
}

Comeau and GCC give me an error.  Comeau says
error: const variable "abc3" requires an initializer
error: const variable "abc1" requires an initializer -- class "pod" has
no explicitly declared default constructor

and same for abc2

GCC says - error: uninitialized const `abc1'
and same for abc2 and abc3

VC7.1 gives no error for abc1,abc2 but gives an error for abc3, and if I
add the "static" specifier to abc3, VC7.1 gives no error.


Adding the static specifier to abc1/2/3 makes no difference to Comeau
and GCC - they still give errors.


8.5 para 9 says
<quote>
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. Otherwise, if no initializer is specified for a nonstatic
object, the object and its subobjects, if any, have an indeterminate
initial value90); if the object or any of its subobjects are of
const-qualified type, the program is ill-formed.
<end quote>


IMO the first sentence has *potential* for multiple interpretations  -
is the part following the semicolon talking about non-POD class types
only or all const objects that have no initializer?  The phrase
"underlying class type" implies that the first sentence applies to non
POD class types only.  I think the wording should be clearer.

The second sentence outlaws non static const objects with no initializer
that don't fall into the category described in the first sentence.

This appears to mean that static const PODs are not required to have an
initializer and Comeau, GCC and VC7.1 are wrong, probably due to the
confusing first sentence in 8.5/9.  VC7.1 appears to be inconsistent in
its interpretation of 8.5/9 in that it requires the const int to have
the static keyword, as if "static" in 8.5/9 is referring to linkage and
not storage class  - the keyword static applied to abc3 makes no
difference to either the linkage or storage class of abc3.


This is a nuisance because I have a POD with a lot of bitfield bool
members and I wish to create a const object with all bool flags set to
false.  I should be able to declare a const object in static storage
with no initializer and rely on zero-initialization of static storage at
startup, however I am forced to either
1. Supply an initializer using a brace enclosed list.
2. Supply an initializer of the form T()
3. Supply a do nothing default constructor.

For 1), GCC gives me a warning for every member that I don't supply an
initializer for and may also involve unnecessary overhead.  Item 2
results in unnecessary code being generated.  Item 3 makes the class a
non POD and is "odd".


Regarding the first sentence of 8.5/9, it may be that scholars of the
English language could say that it's unambiguous even without the phrase
"underlying class type" but shouldn't the standard be as clear as
possible and not rely on "tricky" phrases that may or may not have been
the intent of the authors.

Assuming my compilers are wrong to give errors for the above code?,
would  the following be an improvement to 8.5/9?


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.


The last bullet could possibly be changed to
-- Otherwise, the object and its subobjects ...

I believe C99 allows the above code and doesn't even require an
initializer for a const automatic object?

---
[ 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                       ]