Constness of the container of shared_ptr and the constness of it elements

Discussion in 'C++' started by PengYu.UT@gmail.com, Apr 2, 2006.

  1. Guest

    In the following program, I want an iterator contain pointer pointing
    to constant object not const pointer. If it is possible would you
    please let me know how to do it?

    #include <boost/shared_ptr.hpp>
    #include <vector>
    #include <iterator>
    #include <iostream>

    class trial {
    public:
    void const_fun() const {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
    void non_const_fun() {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
    }
    };

    int main(){
    std::vector<boost::shared_ptr<trial> > v;
    v.push_back(boost::shared_ptr<trial>(new trial));
    {
    std::vector<boost::shared_ptr<trial> >::iterator it = v.begin();
    (*it)->const_fun();
    (*it)->non_const_fun();
    }
    {
    std::vector<boost::shared_ptr<trial> >::const_iterator it =
    v.begin();
    (*it)->const_fun();
    (*it)->non_const_fun();//want a const trial, this function should
    not be called.
    }
    {
    std::vector<boost::shared_ptr<const trial> >::iterator it =
    v.begin();//compile error
    (*it)->const_fun();
    (*it)->non_const_fun();
    }

    std::vector<boost::shared_ptr<const trial> > v_const = v;//error,
    //is there any conversion of
    this kind?

    return EXIT_SUCCESS;
    }
     
    , Apr 2, 2006
    #1
    1. Advertising

  2. On 2 Apr 2006 13:59:58 -0700, ""
    <> wrote:
    >In the following program, I want an iterator contain pointer pointing
    >to constant object not const pointer. If it is possible would you
    >please let me know how to do it?


    No. Standard containers are for values only, not for pointers (neither
    real nor "smart").

    Best wishes,
    Roland Pibinger
     
    Roland Pibinger, Apr 2, 2006
    #2
    1. Advertising

  3. Ian Collins Guest

    Re: Constness of the container of shared_ptr and the constness ofit elements

    Roland Pibinger wrote:
    > On 2 Apr 2006 13:59:58 -0700, ""
    > <> wrote:
    >
    >>In the following program, I want an iterator contain pointer pointing
    >>to constant object not const pointer. If it is possible would you
    >>please let me know how to do it?

    >
    >
    > No. Standard containers are for values only, not for pointers (neither
    > real nor "smart").
    >

    Care to elaborate? Containers are often used for both pointers and
    smart pointers.

    --
    Ian Collins.
     
    Ian Collins, Apr 2, 2006
    #3
  4. Daniel T. Guest

    In article <>,
    "" <> wrote:

    > In the following program, I want an iterator contain pointer pointing
    > to constant object not const pointer. If it is possible would you
    > please let me know how to do it?


    You have to wrap the vector in a class of your own that prohibits such
    use.

    > #include <boost/shared_ptr.hpp>
    > #include <vector>
    > #include <iterator>
    > #include <iostream>
    >
    > class trial {
    > public:
    > void const_fun() const {
    > std::cout << __PRETTY_FUNCTION__ << std::endl;
    > }
    > void non_const_fun() {
    > std::cout << __PRETTY_FUNCTION__ << std::endl;
    > }
    > };
    >
    > int main(){
    > std::vector<boost::shared_ptr<trial> > v;
    > v.push_back(boost::shared_ptr<trial>(new trial));
    > {
    > std::vector<boost::shared_ptr<trial> >::iterator it = v.begin();
    > (*it)->const_fun();
    > (*it)->non_const_fun();
    > }
    > {
    > std::vector<boost::shared_ptr<trial> >::const_iterator it =
    > v.begin();
    > (*it)->const_fun();
    > (*it)->non_const_fun();//want a const trial, this function should
    > not be called.


    That function should be called. The const_iterator means that the
    pointer value itself is const, not the trial object it points to. IE you
    can change the trial object, but you can't replace it with a different
    trial object.

    > }
    > {
    > std::vector<boost::shared_ptr<const trial> >::iterator it =
    > v.begin();//compile error
    > (*it)->const_fun();
    > (*it)->non_const_fun();
    > }
    >
    > std::vector<boost::shared_ptr<const trial> > v_const = v;//error,
    > //is there any conversion of
    > this kind?


    No, nor would there be if you were using bald pointers.

    > return EXIT_SUCCESS;
    > }




    --
    Magic depends on tradition and belief. It does not welcome observation,
    nor does it profit by experiment. On the other hand, science is based
    on experience; it is open to correction by observation and experiment.
     
    Daniel T., Apr 3, 2006
    #4
  5. Guest

    Daniel T. wrote:
    > In article <>,
    > "" <> wrote:
    >
    > > In the following program, I want an iterator contain pointer pointing
    > > to constant object not const pointer. If it is possible would you
    > > please let me know how to do it?

    >
    > You have to wrap the vector in a class of your own that prohibits such
    > use.
    >
    > > #include <boost/shared_ptr.hpp>
    > > #include <vector>
    > > #include <iterator>
    > > #include <iostream>
    > >
    > > class trial {
    > > public:
    > > void const_fun() const {
    > > std::cout << __PRETTY_FUNCTION__ << std::endl;
    > > }
    > > void non_const_fun() {
    > > std::cout << __PRETTY_FUNCTION__ << std::endl;
    > > }
    > > };
    > >
    > > int main(){
    > > std::vector<boost::shared_ptr<trial> > v;
    > > v.push_back(boost::shared_ptr<trial>(new trial));
    > > {
    > > std::vector<boost::shared_ptr<trial> >::iterator it = v.begin();
    > > (*it)->const_fun();
    > > (*it)->non_const_fun();
    > > }
    > > {
    > > std::vector<boost::shared_ptr<trial> >::const_iterator it =
    > > v.begin();
    > > (*it)->const_fun();
    > > (*it)->non_const_fun();//want a const trial, this function should
    > > not be called.

    >
    > That function should be called. The const_iterator means that the
    > pointer value itself is const, not the trial object it points to. IE you
    > can change the trial object, but you can't replace it with a different
    > trial object.
    >
    > > }
    > > {
    > > std::vector<boost::shared_ptr<const trial> >::iterator it =
    > > v.begin();//compile error
    > > (*it)->const_fun();
    > > (*it)->non_const_fun();
    > > }
    > >
    > > std::vector<boost::shared_ptr<const trial> > v_const = v;//error,
    > > //is there any conversion of
    > > this kind?

    >
    > No, nor would there be if you were using bald pointers.


    If I have some function which can accept a vector of objects and it
    doesn't change these objects, I have to define the function accept a
    vector of objects (not const objects), because the answer to the above
    question is "NO". Is it a drawback of the STL contain? Could it be
    improved?
     
    , Apr 3, 2006
    #5
  6. Daniel T. Guest

    In article <>,
    "" <> wrote:

    > Daniel T. wrote:
    > > In article <>,
    > > "" <> wrote:
    > >
    > > > In the following program, I want an iterator contain pointer pointing
    > > > to constant object not const pointer. If it is possible would you
    > > > please let me know how to do it?

    > >
    > > You have to wrap the vector in a class of your own that prohibits such
    > > use.
    > >
    > > > #include <boost/shared_ptr.hpp>
    > > > #include <vector>
    > > > #include <iterator>
    > > > #include <iostream>
    > > >
    > > > class trial {
    > > > public:
    > > > void const_fun() const {
    > > > std::cout << __PRETTY_FUNCTION__ << std::endl;
    > > > }
    > > > void non_const_fun() {
    > > > std::cout << __PRETTY_FUNCTION__ << std::endl;
    > > > }
    > > > };
    > > >
    > > > int main(){
    > > > std::vector<boost::shared_ptr<trial> > v;
    > > > v.push_back(boost::shared_ptr<trial>(new trial));
    > > > {
    > > > std::vector<boost::shared_ptr<trial> >::iterator it = v.begin();
    > > > (*it)->const_fun();
    > > > (*it)->non_const_fun();
    > > > }
    > > > {
    > > > std::vector<boost::shared_ptr<trial> >::const_iterator it =
    > > > v.begin();
    > > > (*it)->const_fun();
    > > > (*it)->non_const_fun();//want a const trial, this function should
    > > > not be called.

    > >
    > > That function should be called. The const_iterator means that the
    > > pointer value itself is const, not the trial object it points to. IE you
    > > can change the trial object, but you can't replace it with a different
    > > trial object.
    > >
    > > > }
    > > > {
    > > > std::vector<boost::shared_ptr<const trial> >::iterator it =
    > > > v.begin();//compile error
    > > > (*it)->const_fun();
    > > > (*it)->non_const_fun();
    > > > }
    > > >
    > > > std::vector<boost::shared_ptr<const trial> > v_const = v;//error,
    > > > //is there any conversion of
    > > > this kind?

    > >
    > > No, nor would there be if you were using bald pointers.

    >
    > If I have some function which can accept a vector of objects and it
    > doesn't change these objects, I have to define the function accept a
    > vector of objects (not const objects), because the answer to the above
    > question is "NO". Is it a drawback of the STL contain? Could it be
    > improved?


    It's not a drawback of the STL containers. It is a proper and necessary
    requirement. The object that the container is going to be destroying is
    the one that is (and should be) const when the container is const. If
    the container is holding pointers, then *that* is what is, and should
    be, const.



    --
    Magic depends on tradition and belief. It does not welcome observation,
    nor does it profit by experiment. On the other hand, science is based
    on experience; it is open to correction by observation and experiment.
     
    Daniel T., Apr 3, 2006
    #6
  7. red floyd Guest

    Re: Constness of the container of shared_ptr and the constness ofit elements

    Roland Pibinger wrote:
    > On 2 Apr 2006 13:59:58 -0700, ""
    > <> wrote:
    >> In the following program, I want an iterator contain pointer pointing
    >> to constant object not const pointer. If it is possible would you
    >> please let me know how to do it?

    >
    > No. Standard containers are for values only, not for pointers (neither
    > real nor "smart").
    > =


    Really, Roland? How would you manage a container of polymorphic objects
    (classic case in point, a list or vector of Shapes).
     
    red floyd, Apr 3, 2006
    #7
  8. red floyd Guest

    Re: Constness of the container of shared_ptr and the constness ofit elements

    red floyd wrote:
    > Roland Pibinger wrote:
    >> On 2 Apr 2006 13:59:58 -0700, ""
    >> <> wrote:
    >>> In the following program, I want an iterator contain pointer pointing
    >>> to constant object not const pointer. If it is possible would you
    >>> please let me know how to do it?

    >>
    >> No. Standard containers are for values only, not for pointers (neither
    >> real nor "smart").
    >> =

    >
    > Really, Roland? How would you manage a container of polymorphic objects
    > (classic case in point, a list or vector of Shapes).


    Follow-up. You can store pointers (raw or smart) in a Standard
    container. In fact, that's the only way to maintain a container of
    polymorphic objects.

    The thing is that if you store raw pointers in a container, then *you*
    are responsible for managing the lifetime of those pointers -- on a
    recent project, we were using raw pointers (legacy code), and I made a
    big deal during design reviews that pointer ownership and lifetime
    maintenance had to be specified in the design (we were storing them in
    containers).

    If you use a smart pointer, then the smart pointer manages the lifetime
    of the pointer, and you don't have to deal with it.
     
    red floyd, Apr 3, 2006
    #8
  9. Re: Constness of the container of shared_ptr and the constness of it elements

    On Mon, 03 Apr 2006 10:37:28 +1200, Ian Collins <>
    wrote:
    >Roland Pibinger wrote:
    >> No. Standard containers are for values only, not for pointers (neither
    >> real nor "smart").
    >>

    >Care to elaborate? Containers are often used for both pointers and
    >smart pointers.


    'Value semantics' is one of the central characteristics of STL. All
    containers, iterators and algorithms are designed for values only. You
    may also use pointers as template arguments but they cause various
    problems: clumsiness in usage, no 'const correctness' (see above),
    algorithm mismatch (algorithms refer to pointers, not pointed-to
    objects), ...
    A container for pointers needs a design that is especially made for
    pointers. Many library vendors provide (non-Standard) containers for
    pointers, see e.g. CTypedPtrArray (MFC), QPtrVector (Qt), ... IMO, the
    lack of appropriate containers for pointers is one of the major
    reasons for the low acceptance of STL in the real world.

    Best wishes,
    Roland Pibinger
     
    Roland Pibinger, Apr 3, 2006
    #9
  10. Re: Constness of the container of shared_ptr and the constness of it elements

    On Mon, 03 Apr 2006 04:13:15 GMT, red floyd <> wrote:
    >Roland Pibinger wrote:
    >> No. Standard containers are for values only, not for pointers (neither
    >> real nor "smart").
    >> =

    >Really, Roland?


    Yes, really!

    >How would you manage a container of polymorphic objects
    >(classic case in point, a list or vector of Shapes).


    With a container for pointers:
    http://www.codeproject.com/vcpp/stl/ptr_vecto.asp

    Best wishes,
    Roland Pibinger
     
    Roland Pibinger, Apr 3, 2006
    #10
  11. Re: Constness of the container of shared_ptr and the constness of it elements

    On Mon, 03 Apr 2006 16:16:36 GMT, red floyd <> wrote:
    >red floyd wrote:
    >Follow-up. You can store pointers (raw or smart) in a Standard
    >container. In fact, that's the only way to maintain a container of
    >polymorphic objects.


    Not the only way. You can store polymorphic objects in any container
    that is appropriate for polymorphic objects. Just the Standard
    containers are not.

    >The thing is that if you store raw pointers in a container, then *you*
    >are responsible for managing the lifetime of those pointers


    Containment an ownership management are two different tasks. A
    container for pointers should be first and foremost a container, not
    an object manager.

    >-- on a
    >recent project, we were using raw pointers (legacy code), and I made a
    >big deal during design reviews that pointer ownership and lifetime
    >maintenance had to be specified in the design (we were storing them in
    >containers).


    The rule of thumb is simple: Release resources in destructors. WRT
    containers for pointers this means that the destructor of the
    containing object shall delete the pointed-to objects in the
    container.
    A general-purpose container for pointers shall not and cannot delete
    any objects (since it doesn't know how they have been created).

    >If you use a smart pointer, then the smart pointer manages the lifetime
    >of the pointer, and you don't have to deal with it.


    The "smart" pointer solution means one resource manager (which
    dynamically allocates a ref-counter) for each pointed-to object.
    Moreover, "smart" pointers cause many unsmart problems. I would avoid
    them.

    Best wishes,
    Roland Pibinger
     
    Roland Pibinger, Apr 3, 2006
    #11
  12. mlimber Guest

    wrote:
    > In the following program, I want an iterator contain pointer pointing
    > to constant object not const pointer. If it is possible would you
    > please let me know how to do it?
    >
    > #include <boost/shared_ptr.hpp>
    > #include <vector>
    > #include <iterator>
    > #include <iostream>
    >
    > class trial {
    > public:
    > void const_fun() const {
    > std::cout << __PRETTY_FUNCTION__ << std::endl;
    > }
    > void non_const_fun() {
    > std::cout << __PRETTY_FUNCTION__ << std::endl;
    > }
    > };
    >
    > int main(){
    > std::vector<boost::shared_ptr<trial> > v;
    > v.push_back(boost::shared_ptr<trial>(new trial));
    > {
    > std::vector<boost::shared_ptr<trial> >::iterator it = v.begin();
    > (*it)->const_fun();
    > (*it)->non_const_fun();
    > }
    > {
    > std::vector<boost::shared_ptr<trial> >::const_iterator it =
    > v.begin();
    > (*it)->const_fun();
    > (*it)->non_const_fun();//want a const trial, this function should
    > not be called.
    > }
    > {
    > std::vector<boost::shared_ptr<const trial> >::iterator it =
    > v.begin();//compile error
    > (*it)->const_fun();
    > (*it)->non_const_fun();
    > }
    >
    > std::vector<boost::shared_ptr<const trial> > v_const = v;//error,
    > //is there any conversion of
    > this kind?
    >
    > return EXIT_SUCCESS;
    > }


    There have been several debates on the Boost development group about
    whether or not to give smart pointers "deep constness" (see for
    instance http://thread.gmane.org/gmane.comp.lib.boost.devel/95836).
    This issue is particularly important when considering const member
    functions that can change the pointees of its class' const members. For
    instance,

    class Foo
    {
    int *pi_;
    std::vector<int> vi_;
    public:
    // ...

    void Bar() const
    {
    pi_[0] = 0; // Ok, but unintended?
    vi_[0] = 0; // Error! vi_ is const here
    }
    };

    Boost smart pointers, like raw pointers, allow modification of the
    pointees, but some standard containers like std::vector don't. Because
    the goal for boost::shared_ptr was to be "as close as possible to a raw
    pointer, but no closer", the final decision was to make it not support
    deep constness.

    To change the behavior of a smart pointer for members, you might use a
    wrapper class like this:

    template <typename T>
    class deep_shared_ptr
    {
    public:
    // Constructors
    deep_shared_ptr() {}

    template<typename Y>
    deep_shared_ptr( Y* const y ) : m_ptr( y ) {}

    template<typename Y>
    deep_shared_ptr( boost::shared_ptr<Y>& that ) : m_ptr( that ) {}

    template<typename Y>
    deep_shared_ptr( deep_shared_ptr<Y>& that ) : m_ptr( that ) {}


    // The usual operations
    T* operator->() { return m_ptr.operator->(); }
    T& operator*() { return m_ptr.operator*(); }


    // The unusual: make pointee const if pointer is const
    T const* operator->() const { return m_ptr.operator->(); }
    T const& operator*() const { return m_ptr.operator*(); }


    // Reset pass-throughs
    template<typename Y>
    void reset( Y* const y )
    { m_ptr.reset( y ); }

    template<typename Y>
    void reset( boost::shared_ptr<Y>& that )
    { m_ptr.reset( that ); }

    template<typename Y>
    void reset( deep_shared_ptr<Y>& that )
    { m_ptr.reset( that.Get() ); }


    private:
    boost::shared_ptr<T> m_ptr;

    // Disable copying from const deep pointers
    deep_shared_ptr( const deep_shared_ptr& );
    deep_shared_ptr( const boost::shared_ptr<T>& );

    template<typename Y>
    deep_shared_ptr& operator=( const deep_shared_ptr<Y>& );

    template<typename Y>
    deep_shared_ptr& operator=( const boost::shared_ptr<Y>& );
    };

    Unfortunately, as is reflected in the disabled functions, deep pointers
    of this kind do not support normal copy semantics since they don't
    accept a copy from a const deep_shared_ptr and can thus cannot be used
    in standard containers. They can be handy as members, however.

    Cheers! --M
     
    mlimber, Apr 3, 2006
    #12
  13. Ian Collins Guest

    Re: Constness of the container of shared_ptr and the constness ofit elements

    Roland Pibinger wrote:
    > On Mon, 03 Apr 2006 10:37:28 +1200, Ian Collins <>
    > wrote:
    >
    >>Roland Pibinger wrote:
    >>
    >>>No. Standard containers are for values only, not for pointers (neither
    >>>real nor "smart").
    >>>

    >>
    >>Care to elaborate? Containers are often used for both pointers and
    >>smart pointers.

    >
    >
    > 'Value semantics' is one of the central characteristics of STL. All
    > containers, iterators and algorithms are designed for values only. You
    > may also use pointers as template arguments but they cause various
    > problems: clumsiness in usage, no 'const correctness' (see above),
    > algorithm mismatch (algorithms refer to pointers, not pointed-to
    > objects), ...
    > A container for pointers needs a design that is especially made for
    > pointers. Many library vendors provide (non-Standard) containers for
    > pointers, see e.g. CTypedPtrArray (MFC), QPtrVector (Qt), ... IMO, the
    > lack of appropriate containers for pointers is one of the major
    > reasons for the low acceptance of STL in the real world.
    >

    So what disqualifies a smart pointer from being an object that can be
    stored in a container?

    --
    Ian Collins.
     
    Ian Collins, Apr 3, 2006
    #13
  14. Re: Constness of the container of shared_ptr and the constness of it elements

    On Tue, 04 Apr 2006 09:57:47 +1200, Ian Collins <>
    wrote:
    >So what disqualifies a smart pointer from being an object that can be
    >stored in a container?


    It compiles but it doesn't really work. For the reasons pointed out
    above.

    Best wishes,
    Roland Pibinger
     
    Roland Pibinger, Apr 3, 2006
    #14
  15. Ian Collins Guest

    Re: Constness of the container of shared_ptr and the constness ofit elements

    Roland Pibinger wrote:
    > On Tue, 04 Apr 2006 09:57:47 +1200, Ian Collins <>
    > wrote:
    >
    >>So what disqualifies a smart pointer from being an object that can be
    >>stored in a container?

    >
    >
    > It compiles but it doesn't really work. For the reasons pointed out
    > above.
    >

    Well smart pointers can help.

    I'd expect containers to be used as simple storage with pointers, as you
    say, the standard algorithms expect value semantics. It makes no sense
    to apply std::sort to a vector of pointers, but a vector of pointers is
    still preferable to a plain array of pointers.

    If you wanted to use the object pointed to, you could provide the
    appropriate operators on a smart pointer object.

    You could also use a smart pointer to const type to enforce const
    correctness.

    Provided the user understands the limitations, standard containers are a
    good home for (smart) pointers.

    --
    Ian Collins.
     
    Ian Collins, Apr 4, 2006
    #15
    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. Wolfgang Lipp
    Replies:
    1
    Views:
    418
    Patrick TJ McPhee
    Jan 30, 2004
  2. Wolfgang Lipp
    Replies:
    0
    Views:
    498
    Wolfgang Lipp
    Jan 28, 2004
  3. Replies:
    4
    Views:
    831
    Daniel T.
    Feb 16, 2006
  4. Colin Caughie
    Replies:
    1
    Views:
    766
    Shooting
    Aug 29, 2006
  5. Hicham Mouline
    Replies:
    1
    Views:
    423
    Kai-Uwe Bux
    Apr 11, 2010
Loading...

Share This Page