const correctness - should C++ prefer const member over non-const?

Discussion in 'C++' started by fungus, Oct 30, 2008.

  1. fungus

    fungus Guest

    I define this class:


    class foo {
    std::vector<int>data;
    public:

    int operator[](int n) {
    return data[n];
    }
    int operator[](int n) const {
    return data[n];
    }
    };


    Now in my program I do:

    foo myFoo;
    int x = myFoo[123];
    ....


    Should the const version of foo::eek:perator[] be called?

    I think it should, but my compiler disagrees with me.

    What's the correct behavior? Why...?



    --
    <\___/>
    / O O \
    \_____/ FTB.

    http://www.topaz3d.com/ - New 3D editor!
     
    fungus, Oct 30, 2008
    #1
    1. Advertising

  2. fungus

    Jerry Coffin Guest

    In article <7908dabe-5102-4669-bf68-6cd36bedd6a7
    @m74g2000hsh.googlegroups.com>, says...
    > I define this class:
    >
    >
    > class foo {
    > std::vector<int>data;
    > public:
    >
    > int operator[](int n) {
    > return data[n];
    > }
    > int operator[](int n) const {
    > return data[n];
    > }
    > };
    >
    >
    > Now in my program I do:
    >
    > foo myFoo;
    > int x = myFoo[123];
    > ...
    >
    >
    > Should the const version of foo::eek:perator[] be called?


    No.

    > I think it should, but my compiler disagrees with me.


    The compiler's right. The const version should be called for a const
    object. The non-const version should be called for a non-const object.
    If you don't/didn't have a non-const version, then the const version
    could be called -- but it would be called by convertion the non-const to
    a const object first. That's fine (in this case) but it's still a
    conversion. When matching overloaded functions, one that doesn't require
    a conversion is a better match than one that does require a conversion.

    Most people want the const version used on the RHS of an assignment, but
    the non-const for the LHS. To get what that kind of behavior, you
    normally use a proxy object that overloads operator= and operator T.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Oct 30, 2008
    #2
    1. Advertising

  3. fungus

    fungus Guest

    Re: const correctness - should C++ prefer const member overnon-const?

    On Oct 30, 6:31 am, (blargg) wrote:
    >
    > I'm interested in why you think it should call the const version. If it
    > did, when would it ever call the non-const version?


    Ok, maybe I oversimplified it. Supposed operator[]
    returns a reference to the int:

    int& operator[](int n) {
    return data[n];
    }
    int& operator[](int n) const {
    return data[n];
    }

    If the expression is on the RHS of an assignment, should
    the const version be called?


    --
    <\___/>
    / O O \
    \_____/ FTB.

    http://www.topaz3d.com/ - New 3D editor!
     
    fungus, Oct 30, 2008
    #3
  4. fungus

    fungus Guest

    Re: const correctness - should C++ prefer const member overnon-const?

    On Oct 30, 10:21 am, fungus <> wrote:
    >
    > Ok, maybe I oversimplified it. Supposed operator[]
    > returns a reference to the int:
    >


    ....and just before the pedants arrive, suppose it's
    a struct not an int, and I want to access a member
    of the stuct.

    my_struct& operator[](int n) { return data[n]; }
    const my_struct& operator[](int n) const { return data[n]; }

    Why does the compiler choose the non-const version
    for the RHS of an expression...?


    --
    <\___/>
    / O O \
    \_____/ FTB.

    http://www.topaz3d.com/ - New 3D editor!
     
    fungus, Oct 30, 2008
    #4
  5. fungus

    anon Guest

    fungus wrote:
    > I define this class:
    >
    >
    > class foo {
    > std::vector<int>data;
    > public:
    >
    > int operator[](int n) {
    > return data[n];


    Changing this line to this:
    return data.at(n);
    is much safer

    > }
    > int operator[](int n) const {
    > return data[n];
    > }
    > };
    >
    >
    > Now in my program I do:
    >
    > foo myFoo;
    > int x = myFoo[123];
    > ...
    >


    This should call the non-const operator[]

    If you had:
    const foo myFoo;
    int x = myFoo[123];
    then the const version of the operator[] would be used

    >
    > Should the const version of foo::eek:perator[] be called?
    >
    > I think it should, but my compiler disagrees with me.
    >
    > What's the correct behavior? Why...?
    >
     
    anon, Oct 30, 2008
    #5
  6. fungus

    anon Guest

    Re: const correctness - should C++ prefer const member over non-const?

    fungus wrote:
    > On Oct 30, 10:21 am, fungus <> wrote:
    >> Ok, maybe I oversimplified it. Supposed operator[]
    >> returns a reference to the int:
    >>

    >
    > ...and just before the pedants arrive, suppose it's
    > a struct not an int, and I want to access a member
    > of the stuct.
    >
    > my_struct& operator[](int n) { return data[n]; }
    > const my_struct& operator[](int n) const { return data[n]; }
    >
    > Why does the compiler choose the non-const version
    > for the RHS of an expression...?


    Because your myFoo object is not const
     
    anon, Oct 30, 2008
    #6
  7. fungus

    fungus Guest

    Re: const correctness - should C++ prefer const member overnon-const?

    On Oct 30, 6:41 am, Jerry Coffin <> wrote:
    >
    > > Should the const version of foo::eek:perator[] be called?

    >
    > No.
    >
    > > I think it should, but my compiler disagrees with me.

    >
    > The compiler's right.


    Bummer. I've got an object which triggers quite
    a big internal rebuild when you call the non-const
    version and I just noticed it's doing a lot of
    rebuilding because of this assumption.


    --
    <\___/>
    / O O \
    \_____/ FTB.

    http://www.topaz3d.com/ - New 3D editor!
     
    fungus, Oct 30, 2008
    #7
  8. fungus

    SG Guest

    Re: const correctness - should C++ prefer const member overnon-const?

    On 30 Okt., 10:59, fungus <> wrote:
    > Bummer. I've got an object which triggers quite
    > a big internal rebuild when you call the non-const
    > version and I just noticed it's doing a lot of
    > rebuilding because of this assumption.


    You can explicitly convert your object to a const version if you don't
    want the non-const member function to be called in some cases:

    const foo& myConstFoo = myFoo;
    int blah = myConstFoo[42];

    or something like that. static_cast<foo const&>(myFoo)[42] should also
    work as far as I can tell. Though, these kinds of casts are still a
    bit of a mystery to me.

    Cheers,
    SG
     
    SG, Oct 30, 2008
    #8
  9. fungus

    fungus Guest

    Re: const correctness - should C++ prefer const member overnon-const?

    On Oct 30, 11:41 am, (blargg) wrote:
    > I could have sworn "The Design and Evolution of C++"
    > covered the reason behind this, but I couldn't find a
    > reference.


    Maybe you mean section 3.7.1 ?


    --
    <\___/>
    / O O \
    \_____/ FTB.

    http://www.topaz3d.com/ - New 3D editor!
     
    fungus, Oct 30, 2008
    #9
  10. fungus

    fungus Guest

    Re: const correctness - should C++ prefer const member overnon-const?

    On Oct 30, 11:45 am, (blargg) wrote:
    > As others have mentioned, a proxy object with an operator T () and
    > operator = ( T const& ) would be most transparent to the user.


    I don't see how that works for a struct...

    I want operator[] to return a reference to a struct
    and be able to do this:

    Foo f = myStuff.foo;

    and

    myStuff.foo = f;


    With the first one calling the const version of operator[].



    --
    <\___/>
    / O O \
    \_____/ FTB.

    http://www.topaz3d.com/ - New 3D editor!
     
    fungus, Oct 30, 2008
    #10
  11. Re: const correctness - should C++ prefer const member over non-const?

    fungus wrote:

    > Bummer. I've got an object which triggers quite
    > a big internal rebuild when you call the non-const
    > version and I just noticed it's doing a lot of
    > rebuilding because of this assumption.


    Then either the two methods' semantics are too different for a
    single identifier, or the entity making the offending calls shouldn't
    get its hands on a non-const reference, or you should memoize the
    rebuilding method.


    Martin

    --
    Quidquid latine scriptum est, altum videtur.
     
    Martin Eisenberg, Oct 30, 2008
    #11
  12. fungus

    fungus Guest

    Re: const correctness - should C++ prefer const member overnon-const?

    On Oct 30, 1:50 pm, Martin Eisenberg <> wrote:
    > the entity making the offending calls shouldn't
    > get its hands on a non-const reference
    >


    This is probably the best solution. I need both const
    and non const access inside an event handler function
    so I guess I need to make the access more fine-grained.


    --
    <\___/>
    / O O \
    \_____/ FTB.

    http://www.topaz3d.com/ - New 3D editor!
     
    fungus, Oct 30, 2008
    #12
  13. fungus

    James Kanze Guest

    Re: const correctness - should C++ prefer const member overnon-const?

    On Oct 30, 1:15 pm, fungus <> wrote:
    > On Oct 30, 11:45 am, (blargg) wrote:


    > > As others have mentioned, a proxy object with an operator T
    > > () and operator = ( T const& ) would be most transparent to
    > > the user.


    > I don't see how that works for a struct...


    It doesn't, really.

    > I want operator[] to return a reference to a struct and be
    > able to do this:


    > Foo f = myStuff.foo;


    > and


    > myStuff.foo = f;


    > With the first one calling the const version of operator[].


    There are several solutions. The best would be to find a
    compiler modified to allow you to overload operator., and use
    that. But that sort of ruins portability. Otherwise, you can
    overload operator-> in the proxy, and tell your users to use
    that whenever they do a []---it's ugly and counter-intuitive,
    but it works. And for special cases, you can define all of the
    members in the proxy, so that they forward to the correct member
    of owning class. Or you can just require your clients to get a
    reference first, e.g.:
    Whatever const& rf = myStuff[ i ].foo
    Foo f = rf.foo ;

    --
    James Kanze (GABI Software) email:
    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
     
    James Kanze, Oct 30, 2008
    #13
  14. fungus

    fungus Guest

    Re: const correctness - should C++ prefer const member overnon-const?

    On Oct 31, 4:46 am, (blargg) wrote:
    >
    >     class Stuff {
    >     public:
    >         Whatever const& operator [] ( int ) const;
    >         Whatever& modify( int );
    >     };
    >
    >     void user( Stuff& myStuff )
    >     {
    >         Foo f = myStuff[ i ].foo;
    >         // ...
    >         myStuff.modify( i ).foo = f;
    >     }
    >


    This (or variations on it) works too...


    --
    <\___/>
    / O O \
    \_____/ FTB.

    http://www.topaz3d.com/ - New 3D editor!
     
    fungus, Oct 31, 2008
    #14
    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. Replies:
    6
    Views:
    803
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=
    Sep 24, 2006
  2. Replies:
    5
    Views:
    656
    Ivan Vecerina
    Sep 14, 2006
  3. Replies:
    54
    Views:
    1,344
    D'Arcy J.M. Cain
    Apr 3, 2008
  4. Hendrik Maryns
    Replies:
    2
    Views:
    388
    Arne Vajhøj
    Apr 8, 2008
  5. Jake Barnes
    Replies:
    3
    Views:
    120
Loading...

Share This Page