Rationale behind user provided ctor requirement for const objectsof non-POD class types

Discussion in 'C++' started by Nikos Chantziaras, May 23, 2011.

  1. (Originally posted to comp.std.c++, but that newsgroup is dead.)

    Recently, I've seen a compiler (clang) that will not compile code like this:

    struct A {
    A() {}
    };

    class B {
    A a_;
    };

    int foo()
    {
    const B b;
    return 0;
    }

    It will not compile it because 'b' is const B, which does not have a
    user defined ctor. C++'03 [dcl.init] p9 says:

    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.

    Why is that? Why can't a const B constructed the same way as a
    non-const B, using the implicitly defined default constructor?
     
    Nikos Chantziaras, May 23, 2011
    #1
    1. Advertising

  2. * Nikos Chantziaras, on 23.05.2011 11:07:
    > (Originally posted to comp.std.c++, but that newsgroup is dead.)
    >
    > Recently, I've seen a compiler (clang) that will not compile code like this:
    >
    > struct A {
    > A() {}
    > };
    >
    > class B {
    > A a_;
    > };
    >
    > int foo()
    > {
    > const B b;
    > return 0;
    > }
    >
    > It will not compile it because 'b' is const B, which does not have a user
    > defined ctor. C++'03 [dcl.init] p9 says:
    >
    > 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.
    >
    > Why is that? Why can't a const B constructed the same way as a non-const B,
    > using the implicitly defined default constructor?


    Bjarne Stroustrup's "The Design & Evolution of C++" is a good source of answers
    to such questions.

    Unfortunately I don't have it.

    But often these rationales are nothing but common sense. So I guess if you check
    out D&E, and if it gives a rationale, it will be that

    this unchanging "value" shall have been explicitly defined by the source code,
    because generally it makes no sense to /name a value/ and not define that value
    explicitly.

    There are times where it might makes sense (if had been allowed) to write e.g.

    int const someIntValue;

    but from the compiler's point of view this seems like the programmer had
    forgotten to supplyh the value to be named, and anyway in such cases it's no big
    hardship to explicitly state what that value is,

    int const someIntValue = int();

    And likewise in your example.


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, May 23, 2011
    #2
    1. Advertising

  3. On 05/23/2011 01:11 PM, Alf P. Steinbach /Usenet wrote:
    > * Nikos Chantziaras, on 23.05.2011 11:07:
    >> [...]
    >> C++'03 [dcl.init] p9 says:
    >>
    >> 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.
    >>
    >> Why is that? Why can't a const B constructed the same way as a
    >> non-const B,
    >> using the implicitly defined default constructor?

    >[...]
    > But often these rationales are nothing but common sense. So I guess if
    > you check out D&E, and if it gives a rationale, it will be that
    > this unchanging "value" shall have been explicitly defined by the source
    > code, because generally it makes no sense to /name a value/ and not
    > define that value explicitly.
    >
    > There are times where it might makes sense (if had been allowed) to
    > write e.g.
    >
    > int const someIntValue;
    >
    > but from the compiler's point of view this seems like the programmer had
    > forgotten to supplyh the value to be named, and anyway in such cases
    > it's no big hardship to explicitly state what that value is,
    >
    > int const someIntValue = int();
    >
    > And likewise in your example.


    Good thinking, but it doesn't seem to apply. Consider this:

    #include <iostream>

    class A {
    int x_;
    public:
    A() : x_(5) { }
    int x() const { return x_; }
    };

    class B: public A { };

    int main()
    {
    const B b;
    std::cout << b.x() << "\n";
    }

    With compilers that accept this, the output of the program is "5". But
    the C++ standard says that it should not be compilable. In this case
    however, 'b' has a perfectly fine initial state.

    Also, let's not forget that an object can have mutable members, so the
    requirement for a user defined ctor for const B makes even less sense.
     
    Nikos Chantziaras, May 23, 2011
    #3
  4. * Nikos Chantziaras, on 23.05.2011 12:32:
    > On 05/23/2011 01:11 PM, Alf P. Steinbach /Usenet wrote:
    >> * Nikos Chantziaras, on 23.05.2011 11:07:
    >>> [...]
    >>> C++'03 [dcl.init] p9 says:
    >>>
    >>> 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.
    >>>
    >>> Why is that? Why can't a const B constructed the same way as a
    >>> non-const B,
    >>> using the implicitly defined default constructor?

    >> [...]
    >> But often these rationales are nothing but common sense. So I guess if
    >> you check out D&E, and if it gives a rationale, it will be that
    >> this unchanging "value" shall have been explicitly defined by the source
    >> code, because generally it makes no sense to /name a value/ and not
    >> define that value explicitly.
    >>
    >> There are times where it might makes sense (if had been allowed) to
    >> write e.g.
    >>
    >> int const someIntValue;
    >>
    >> but from the compiler's point of view this seems like the programmer had
    >> forgotten to supplyh the value to be named, and anyway in such cases
    >> it's no big hardship to explicitly state what that value is,
    >>
    >> int const someIntValue = int();
    >>
    >> And likewise in your example.

    >
    > Good thinking, but it doesn't seem to apply. Consider this:
    >
    > #include <iostream>
    >
    > class A {
    > int x_;
    > public:
    > A() : x_(5) { }
    > int x() const { return x_; }
    > };
    >
    > class B: public A { };
    >
    > int main()
    > {
    > const B b;
    > std::cout << b.x() << "\n";
    > }


    I think this is completely like the `someIntValue` case. You want any value of
    class `B`, or perhaps the default value. Then for this special case it's no big
    deal to write

    B const b = B();

    just as with the `someIntValue`.


    > With compilers that accept this, the output of the program is "5". But the C++
    > standard says that it should not be compilable. In this case however, 'b' has a
    > perfectly fine initial state.
    >
    > Also, let's not forget that an object can have mutable members, so the
    > requirement for a user defined ctor for const B makes even less sense.


    As I see it mutable members are pretty irrelevant, because their mutability
    should not affect the externally visible state. E.g., a mutable member might be
    used for caching for some costly-to-compute result, for example a matrix
    determinant, but the using code does not see any state change. Thus, declaring a
    `const` object of such a well-designed class is no different; it is conceptually
    to name an unchanging value, which "should" be specified.


    Cheers & hth.,

    - Alf


    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, May 23, 2011
    #4
  5. Nikos Chantziaras

    Balog Pal Guest

    Re: Rationale behind user provided ctor requirement for const objects of non-POD class types

    "Alf P. Steinbach /Usenet" <>
    > I think this is completely like the `someIntValue` case. You want any
    > value of class `B`, or perhaps the default value. Then for this special
    > case it's no big deal to write
    >
    > B const b = B();


    Provided B is copyable :-((. The "can e declaration" bullshit takes its
    usual toll. Normally you'd say

    B const b();

    but that is interpreted as a function.

    At least we know the rationalte for that one: inherited from C without
    change. Just like for() scoping this should be revised too.

    I tried the b{} form with the code example upstream in current Cameau, no
    luck. Not sure whether it is the mandated behavior or just the brace init is
    not yet implemented.
     
    Balog Pal, May 23, 2011
    #5
  6. Nikos Chantziaras

    Öö Tiib Guest

    On May 23, 3:44 pm, "Balog Pal" <> wrote:
    > "Alf P. Steinbach /Usenet" <>
    >
    > > I think this is completely like the `someIntValue` case. You want any
    > > value of class `B`, or perhaps the default value. Then for this special
    > > case it's no big deal to write

    >
    > >   B const b = B();

    >
    > Provided B is copyable :-((.  The "can e declaration" bullshit takes its
    > usual toll. Normally you'd say
    >
    >  B const b();
    >
    > but that is interpreted as a function.


    So you need non-copyable, immutable and default-constructed instance.

    If such need is common then the class may be made to provide reference
    to one with a static member function. I sometimes do it for "null"
    objects.

    B const& b = B::none();

    If you really need separate instance (why?) then aren't there some
    syntax that will be not interpreted as function like 'B const b(());'
    or something?
     
    Öö Tiib, May 25, 2011
    #6
  7. * Öö Tiib, on 25.05.2011 01:04:
    > On May 23, 3:44 pm, "Balog Pal"<> wrote:
    >> "Alf P. Steinbach /Usenet"<>
    >>
    >>> I think this is completely like the `someIntValue` case. You want any
    >>> value of class `B`, or perhaps the default value. Then for this special
    >>> case it's no big deal to write

    >>
    >>> B const b = B();

    >>
    >> Provided B is copyable :-((. The "can e declaration" bullshit takes its
    >> usual toll. Normally you'd say
    >>
    >> B const b();
    >>
    >> but that is interpreted as a function.

    >
    > So you need non-copyable, immutable and default-constructed instance.
    >
    > If such need is common then the class may be made to provide reference
    > to one with a static member function. I sometimes do it for "null"
    > objects.
    >
    > B const& b = B::none();
    >
    > If you really need separate instance (why?) then aren't there some
    > syntax that will be not interpreted as function like 'B const b(());'
    > or something?


    I think that with C++03 rules

    B const& b = B();

    should do it, while with C++98 this would (as I recall) require a copy
    constructor to be accessible.

    But I don't have time to check out the standard, sorry.


    Cheers,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
     
    Alf P. Steinbach /Usenet, May 25, 2011
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ajax Chelsea

    Is array of POD still a POD type?

    Ajax Chelsea, Dec 1, 2003, in forum: C++
    Replies:
    1
    Views:
    350
    Ron Natalie
    Dec 1, 2003
  2. Apricot
    Replies:
    4
    Views:
    536
    velthuijsen
    Apr 16, 2004
  3. NVH
    Replies:
    8
    Views:
    500
    mlimber
    Jul 6, 2006
  4. Javier
    Replies:
    2
    Views:
    574
    James Kanze
    Sep 4, 2007
  5. Himanshu Garg
    Replies:
    1
    Views:
    167
    Himanshu Garg
    Sep 21, 2003
Loading...

Share This Page