const_cast of `T* const t' to `T* t'

Discussion in 'C++' started by AlesD, Jul 12, 2004.

  1. AlesD

    AlesD Guest

    Hello,

    I can't figure out how to build assignment operator for class which
    contains "type* const value".

    --- example ---

    class parent_t;

    class child_t {
    private:
    friend class parent_t;
    // Private c'tor so only parent_t can create child_t
    child_t(parent_t* iparent): parent(iparent) {};
    public:
    parent_t* const parent;
    }

    class parent_t: std::vector<child_t>
    {
    public:
    parent_t(void);
    }

    ---------------

    The problem is that I std::vector<child_t> complains that:

    error: non-static const member `
    parent_t* const child_t::parent' can't use default assignment operator

    and copy constructor of parent_t:

    parent_t::parent_t(const parent_t& other)
    {
    iterator i = begin();
    while (i != end())
    i->parent = this;
    }

    needs to point it's copies of child_t to itself.

    I wanted to resolve this by using const_cast, but I can't figure how to
    change `parent_t* const' to `parent_t*'. Following code

    child_t&
    child_t::eek:perator=(const child_t& other)
    {
    const_cast<parent_t*>(parent) = other.parent;
    }

    gives

    error: assignment of read-only data-member `child_t::parent'

    My book on C++ nor "C++ FAQ Lite" mention this case. Is it possible to
    do it?

    BTW: Even better would be if I could define child_t as

    class child_t {
    private:
    friend class parent_t;
    child_t(parent_t* iparent): parent(iparent) {};
    public:
    parent_t& parent; // <-- reference instead of `* const'
    }

    but I think this is impossible since there is no way how to reseat
    reference.

    Thanks in advance - Ales
     
    AlesD, Jul 12, 2004
    #1
    1. Advertising

  2. "AlesD" <> wrote in message
    news:cctiph$t1m$...
    > Hello,
    >
    > I can't figure out how to build assignment operator for class which
    > contains "type* const value".
    >


    I think you are trying to solve the wrong problem, just don't declare it
    const. Seems the only thing you gain by doing that is a headache.

    john
     
    John Harrison, Jul 12, 2004
    #2
    1. Advertising

  3. AlesD

    Rolf Magnus Guest

    AlesD wrote:

    > Hello,
    >
    > I can't figure out how to build assignment operator for class which
    > contains "type* const value".
    >
    > --- example ---
    >
    > class parent_t;
    >
    > class child_t {
    > private:
    > friend class parent_t;
    > // Private c'tor so only parent_t can create child_t
    > child_t(parent_t* iparent): parent(iparent) {};
    > public:
    > parent_t* const parent;
    > }
    >
    > class parent_t: std::vector<child_t>
    > {
    > public:
    > parent_t(void);
    > }
    >
    > ---------------
    >
    > The problem is that I std::vector<child_t> complains that:
    >
    > error: non-static const member `
    > parent_t* const child_t::parent' can't use default assignment
    > operator


    That's because the default assignment operator will do a memberwise
    assignment. child_t::parent is constant, and you can't assign to
    constants (which is actually why you make something const in the first
    place).

    >
    > and copy constructor of parent_t:
    >
    > parent_t::parent_t(const parent_t& other)
    > {
    > iterator i = begin();
    > while (i != end())
    > i->parent = this;
    > }
    >
    > needs to point it's copies of child_t to itself.


    If you want to modify the parent member, you shouldn't make it const.

    > I wanted to resolve this by using const_cast, but I can't figure how
    > to change `parent_t* const' to `parent_t*'. Following code
    >
    > child_t&
    > child_t::eek:perator=(const child_t& other)
    > {
    > const_cast<parent_t*>(parent) = other.parent;
    > }
    >
    > gives
    >
    > error: assignment of read-only data-member `child_t::parent'


    const_cast is a tool that is usually used to work around design or
    implementation errors in code you don't control. In your case, you
    should just drop the const and all the problems are gone, or
    alternatively, forbid any reparenting or assignment of your class.

    > My book on C++ nor "C++ FAQ Lite" mention this case. Is it possible to
    > do it?


    *const_cast<parent_t**>(&parent) = other.parent;

    But that's very ugly.

    > BTW: Even better would be if I could define child_t as
    >
    > class child_t {
    > private:
    > friend class parent_t;
    > child_t(parent_t* iparent): parent(iparent) {};
    > public:
    > parent_t& parent; // <-- reference instead of `* const'
    > }
    >
    > but I think this is impossible since there is no way how to reseat
    > reference.


    Well, there is one, but you don't really wanna know...
     
    Rolf Magnus, Jul 12, 2004
    #3
  4. AlesD

    AlesD Guest

    John Harrison wrote:
    > "AlesD" <> wrote in message
    > news:cctiph$t1m$...
    >
    >>Hello,
    >>
    >> I can't figure out how to build assignment operator for class which
    >>contains "type* const value".
    >>

    >
    >
    > I think you are trying to solve the wrong problem, just don't declare it
    > const. Seems the only thing you gain by doing that is a headache.
    >
    > john


    Sorry, but it does not help. I want to let users of child_t change
    parent_t via child_t::parent, which would not be possible if I declared
    it as

    const parent_t* parent

    but don't want to let them point it to different instance of parent,
    which would be possible if I declared it as

    parent_t* parent

    Or am I wrong?

    Ales
     
    AlesD, Jul 12, 2004
    #4
  5. "AlesD" <> wrote in message
    news:cctn2s$um7$...
    > John Harrison wrote:
    > > "AlesD" <> wrote in message
    > > news:cctiph$t1m$...
    > >
    > >>Hello,
    > >>
    > >> I can't figure out how to build assignment operator for class which
    > >>contains "type* const value".
    > >>

    > >
    > >
    > > I think you are trying to solve the wrong problem, just don't declare it
    > > const. Seems the only thing you gain by doing that is a headache.
    > >
    > > john

    >
    > Sorry, but it does not help. I want to let users of child_t change
    > parent_t via child_t::parent, which would not be possible if I declared
    > it as
    >
    > const parent_t* parent
    >
    > but don't want to let them point it to different instance of parent,
    > which would be possible if I declared it as
    >
    > parent_t* parent
    >
    > Or am I wrong?
    >
    > Ales


    Well don't declare parent as public (public data is almost always a bad idea
    anyway). Write

    class child_t
    {
    public:
    parent_t* get_parent() const
    {
    return parent;
    }
    private:
    parent_t* parent;
    };

    The absence of a set_parent method will stop the users of child_t from
    changing parent.

    john
     
    John Harrison, Jul 12, 2004
    #5
  6. AlesD

    AlesD Guest

    Rolf Magnus wrote:
    > const_cast is a tool that is usually used to work around design or
    > implementation errors in code you don't control. In your case, you
    > should just drop the const and all the problems are gone, or
    > alternatively, forbid any reparenting or assignment of your class.


    You are right - I found solution which is clear:

    class child_t
    {
    private:
    parent_t* pparent;
    public:
    parent_t* parent(void) {return parent;};
    }

    This way I the users of child_t can modify parent, but can't "assign"
    child to different parent.

    My last question is about efficiency. I suppose that good compiler (g++
    ??) would inline child_t::parent() and optimize it that calling it will
    be equal to direct use of child_t::pparent.

    Is it true or is there any cost for encapsulating parent_t* this way?

    AlesD
     
    AlesD, Jul 12, 2004
    #6
  7. AlesD

    Rolf Magnus Guest

    AlesD wrote:

    > Rolf Magnus wrote:
    >> const_cast is a tool that is usually used to work around design or
    >> implementation errors in code you don't control. In your case, you
    >> should just drop the const and all the problems are gone, or
    >> alternatively, forbid any reparenting or assignment of your class.

    >
    > You are right - I found solution which is clear:
    >
    > class child_t
    > {
    > private:
    > parent_t* pparent;
    > public:
    > parent_t* parent(void) {return parent;};


    Drop the semicolon after the curly brace.

    > }


    Add a semicolon after the curly brace. ;-)

    >
    > This way I the users of child_t can modify parent, but can't "assign"
    > child to different parent.


    Yes, that's the typical solution to it.

    >
    > My last question is about efficiency. I suppose that good compiler
    > (g++ ??) would inline child_t::parent() and optimize it that calling
    > it will be equal to direct use of child_t::pparent.


    Yes. I'd expect the code that the compiler produces to be the same as if
    the member was directly accessed, but it might depend on the
    optimization level you set.
     
    Rolf Magnus, Jul 12, 2004
    #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. Replies:
    11
    Views:
    1,143
  2. Javier
    Replies:
    2
    Views:
    607
    James Kanze
    Sep 4, 2007
  3. Erik Wikström
    Replies:
    3
    Views:
    533
    Alf P. Steinbach
    Feb 15, 2008
  4. 0m
    Replies:
    26
    Views:
    1,162
    Tim Rentsch
    Nov 10, 2008
  5. fungus
    Replies:
    13
    Views:
    930
    fungus
    Oct 31, 2008
Loading...

Share This Page