Const/non-const pointer returning method

Discussion in 'C++' started by Jens Thoms Toerring, May 25, 2010.

  1. Hi,

    I am rather new to C++ and have run into a problem where I
    haven't found an answer yet by searching (probably didn't find
    the right search terms). I Have this simple program:

    #include <iostream>

    class A
    {
    public:
    A( int i ) : m_ip( new int[ i ] ) { }
    int const * ip( ) const { std::cout << "const\n"; return m_ip; }
    int * ip( ) const { std::cerr << "non-const\n"; return m_ip; }

    private:
    int * m_ip;
    };

    int main( )
    {
    A a( 10 );
    int const * ip = a.ip( );
    std::cout << ip[ 2 ] << '\n';
    }

    My exectation was that when calling ip() to get a const pointer
    the compiler would be able to figure out I want it to use the
    first ip() method that returns a const pointer. But it turns out
    that always the second one is invoked. I'm not sure why and if
    there's a way that I can make it pick the second one (short of
    using different names for the methods)? I also noticed the same
    effect when using const versus non-const references as return
    values, also there the non-const returning function is called
    eben when one asks for a const reference. Does all this only
    work when overloading the [] operator?

    Best regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, May 25, 2010
    #1
    1. Advertising

  2. Jens Thoms Toerring

    Kai-Uwe Bux Guest

    Jens Thoms Toerring wrote:

    > Hi,
    >
    > I am rather new to C++ and have run into a problem where I
    > haven't found an answer yet by searching (probably didn't find
    > the right search terms). I Have this simple program:
    >
    > #include <iostream>
    >
    > class A
    > {
    > public:
    > A( int i ) : m_ip( new int[ i ] ) { }
    > int const * ip( ) const { std::cout << "const\n"; return m_ip; }
    > int * ip( ) const { std::cerr << "non-const\n"; return m_ip; }
    >
    > private:
    > int * m_ip;
    > };
    >
    > int main( )
    > {
    > A a( 10 );
    > int const * ip = a.ip( );
    > std::cout << ip[ 2 ] << '\n';
    > }


    Remark: as an illustration for the problem of which member function is
    called, the code is fine. Considered on its own, however, class A leaves
    room for improvement, e.g., with regard to memory management and
    encapsulation.

    > My exectation was that when calling ip() to get a const pointer
    > the compiler would be able to figure out I want it to use the
    > first ip() method that returns a const pointer. But it turns out
    > that always the second one is invoked.


    You will have to adjust your expectations (if you have not already done so).
    The object a was not declared const. Hence any method call a.method() will
    always invoke the non-const version.

    > I'm not sure why and if
    > there's a way that I can make it pick the second one (short of
    > using different names for the methods)?


    Yes, you could do:

    A a ( 10 );
    A const & b ( a ); // be is a const alias for the object a.
    int const * ip = b.ip();

    Alternatively, some trickery using casts would do.

    BTW: why would you want the const method invoked?


    > I also noticed the same
    > effect when using const versus non-const references as return
    > values, also there the non-const returning function is called
    > eben when one asks for a const reference. Does all this only
    > work when overloading the [] operator?


    The operator[] is not different: the const version is called on const
    objects and the non-const version is called on non-const objects. So it is
    not clear, what you observed.


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, May 25, 2010
    #2
    1. Advertising

  3. Jens Thoms Toerring

    Salt_Peter Guest

    On May 25, 2:03 pm, (Jens Thoms Toerring) wrote:
    > Hi,
    >
    >   I am rather new to C++ and have run into a problem where I
    > haven't found an answer yet by searching (probably didn't find
    > the right search terms). I Have this simple program:
    >
    > #include <iostream>
    >
    > class A
    > {
    >   public:
    >     A( int i ) : m_ip( new int[ i ] ) { }
    >     int const * ip( ) const { std::cout << "const\n"; return m_ip; }
    >     int * ip( ) const { std::cerr << "non-const\n"; return m_ip; }
    >
    >   private:
    >     int * m_ip;
    >
    > };
    >
    > int main( )
    > {
    >     A a( 10 );
    >     int const * ip = a.ip( );
    >     std::cout << ip[ 2 ] << '\n';
    >
    > }
    >
    > My exectation was that when calling ip() to get a const pointer
    > the compiler would be able to figure out I want it to use the
    > first ip() method that returns a const pointer. But it turns out
    > that always the second one is invoked. I'm not sure why and if
    > there's a way that I can make it pick the second one (short of
    > using different names for the methods)? I also noticed the same
    > effect when using const versus non-const references as return
    > values, also there the non-const returning function is called
    > eben when one asks for a const reference. Does all this only
    > work when overloading the [] operator?
    >
    >                             Best regards, Jens
    > --
    >   \   Jens Thoms Toerring  ___      
    >    \__________________________      http://toerring.de


    first off, the following is not a const ptr:
    int const * p; // mutable pointer to a constant
    but this is a const ptr to a mutable integer:
    int * const p

    in C++, one would instead use a std::vector with [] or at(), in the
    case you really do prefer a primitive array, use a template.

    template< typename T, std::size_t SIZE >
    class A

    T m_t[ SIZE ];
    public:
    A() { } // def ctor required for type T
    T& operator[](const std::size_t i) { return m_t; }
    };

    Automatic allocation is safer, easier and preferred. Only new when you
    absolutely must.
    Salt_Peter, May 25, 2010
    #3
  4. * Jens Thoms Toerring, on 25.05.2010 20:03:
    >
    > I am rather new to C++ and have run into a problem where I
    > haven't found an answer yet by searching (probably didn't find
    > the right search terms). I Have this simple program:
    >
    > #include<iostream>
    >
    > class A
    > {
    > public:
    > A( int i ) : m_ip( new int[ i ] ) { }
    > int const * ip( ) const { std::cout<< "const\n"; return m_ip; }
    > int * ip( ) const { std::cerr<< "non-const\n"; return m_ip; }
    >
    > private:
    > int * m_ip;
    > };
    >
    > int main( )
    > {
    > A a( 10 );
    > int const * ip = a.ip( );
    > std::cout<< ip[ 2 ]<< '\n';
    > }


    Do you?


    <example>
    C:\test> gnuc x.cpp
    x.cpp:8: error: 'int* A::ip() const' cannot be overloaded
    x.cpp:7: error: with 'const int* A::ip() const'

    C:\test> msvc x.cpp
    x.cpp
    x.cpp(8) : error C2556: 'int *A::ip(void) const' : overloaded function differs
    only by return type from 'const int *A::i
    p(void) const'
    x.cpp(7) : see declaration of 'A::ip'
    x.cpp(8) : error C2373: 'A::ip' : redefinition; different type modifiers
    x.cpp(7) : see declaration of 'A::ip'
    x.cpp(8) : error C2143: syntax error : missing ';' before '<<'
    x.cpp(8) : warning C4517: access-declarations are deprecated; member
    using-declarations provide a better alternative
    x.cpp(8) : error C2886: 'std::cerr' : symbol cannot be used in a member
    using-declaration
    C:\Program Files\Microsoft Visual Studio .NET
    2003\Vc7\include\iostream(14) : see declaration of 'std::cerr'
    x.cpp(8) : error C2238: unexpected token(s) preceding ';'
    x.cpp(8) : error C2059: syntax error : 'return'
    x.cpp(8) : error C2238: unexpected token(s) preceding ';'
    x.cpp(10) : error C2143: syntax error : missing ';' before ':'
    x.cpp(10) : error C2059: syntax error : ':'
    x.cpp(12) : error C2059: syntax error : '}'
    x.cpp(12) : error C2143: syntax error : missing ';' before '}'
    x.cpp(12) : error C2059: syntax error : '}'
    x.cpp(17) : error C2264: 'A::ip' : error in function definition or declaration;
    function not called

    C:\test> _
    </example>



    > My exectation was that when calling ip() to get a const pointer
    > the compiler would be able to figure out I want it to use the
    > first ip() method that returns a const pointer. But it turns out
    > that always the second one is invoked.


    I rather doubt it.

    First your program needs to compile.


    > I'm not sure why and if
    > there's a way that I can make it pick the second one (short of
    > using different names for the methods)? I also noticed the same
    > effect when using const versus non-const references as return
    > values, also there the non-const returning function is called
    > eben when one asks for a const reference. Does all this only
    > work when overloading the [] operator?


    As a first step, get your program to compile.

    You can safely disregard the earlier comments in this thread until your code
    compiles.

    And then it may turn out that the code that compiles is not what those comments
    are about.


    Cheers & hth.,

    - Alf

    --
    blog at <url: http://alfps.wordpress.com>
    Alf P. Steinbach, May 25, 2010
    #4
  5. On May 25, 10:03 pm, (Jens Thoms Toerring) wrote:
    > Hi,
    >
    >   I am rather new to C++ and have run into a problem where I
    > haven't found an answer yet by searching (probably didn't find
    > the right search terms). I Have this simple program:
    >
    > #include <iostream>
    >
    > class A
    > {
    >   public:
    >     A( int i ) : m_ip( new int[ i ] ) { }
    >     int const * ip( ) const { std::cout << "const\n"; return m_ip; }
    >     int * ip( ) const { std::cerr << "non-const\n"; return m_ip; }
    >
    >   private:
    >     int * m_ip;
    >
    > };
    >
    > int main( )
    > {
    >     A a( 10 );
    >     int const * ip = a.ip( );
    >     std::cout << ip[ 2 ] << '\n';
    >
    > }
    >
    > My exectation was that when calling ip() to get a const pointer
    > the compiler would be able to figure out I want it to use the
    > first ip() method that returns a const pointer. But it turns out
    > that always the second one is invoked. I'm not sure why and if
    > there's a way that I can make it pick the second one (short of
    > using different names for the methods)? I also noticed the same
    > effect when using const versus non-const references as return
    > values, also there the non-const returning function is called
    > eben when one asks for a const reference. Does all this only
    > work when overloading the [] operator?
    >
    >                             Best regards, Jens
    > --
    >   \   Jens Thoms Toerring  ___      
    >    \__________________________      http://toerring.de


    Hi Jens

    At first your code doesn't work. You can't overload
    a function just base on different return type.
    I guess your ip member functions should be like this:
    int const * ip( ) const { std::cout << "const\n"; return m_ip; }
    int * ip( ) { std::cerr << "non-const\n"; return m_ip; }
    Second, if you allocate memory in construtor,
    you must free it in destructor:
    A( int i ) : m_ip( new int) { } // new an array
    ~A() { delete [] ip; } // delete the array
    Third, You didn't initialize your array. Constructor
    is the best way for initialization. For example:
    A( int i ) : m_ip( new int[ i ] )
    {
    std::fill(m_ip, m_ip + i, 0);
    }
    about your question:
    the const member function means
    1. You don't want to change the state of object via it
    2. For const object, just const member function should be called.
    It is the obvious result of #1

    See the following code:
    A a( 10 );
    int const * ip = a.ip();
    ip[0]++; // error *ip is const;
    int* ip2 = a.ip();
    ip2[1]++; // OK: *ip2 is not const
    const A a2(20);
    a2.ip(); // calling const ip

    Regards,
    -- Saeed Amrollahi
    Saeed Amrollahi, May 25, 2010
    #5
  6. Kai-Uwe Bux <> wrote:
    > Jens Thoms Toerring wrote:
    > > I am rather new to C++ and have run into a problem where I
    > > haven't found an answer yet by searching (probably didn't find
    > > the right search terms). I Have this simple program:
    > >
    > > #include <iostream>
    > >
    > > class A
    > > {
    > > public:
    > > A( int i ) : m_ip( new int[ i ] ) { }
    > > int const * ip( ) const { std::cout << "const\n"; return m_ip; }

    ^^^^^
    Sorry, that was a mistake just before copy-and-paste...

    > > int * ip( ) const { std::cerr << "non-const\n"; return m_ip; }
    > >
    > > private:
    > > int * m_ip;
    > > };
    > >
    > > int main( )
    > > {
    > > A a( 10 );
    > > int const * ip = a.ip( );
    > > std::cout << ip[ 2 ] << '\n';
    > > }


    > Remark: as an illustration for the problem of which member function is
    > called, the code is fine. Considered on its own, however, class A leaves
    > room for improvement, e.g., with regard to memory management and
    > encapsulation.


    Yes, of course, this wasn't meant to be production quality code
    but just a bare-bones example, so it leaks memory etc.

    > > My exectation was that when calling ip() to get a const pointer
    > > the compiler would be able to figure out I want it to use the
    > > first ip() method that returns a const pointer. But it turns out
    > > that always the second one is invoked.


    > You will have to adjust your expectations (if you have not already done so).
    > The object a was not declared const. Hence any method call a.method() will
    > always invoke the non-const version.


    Well, I am in the process of adjusting my expectations all the
    time;-) That's part of the fun of learning a new language...

    > > I'm not sure why and if
    > > there's a way that I can make it pick the second one (short of
    > > using different names for the methods)?


    > Yes, you could do:


    > A a ( 10 );
    > A const & b ( a ); // be is a const alias for the object a.
    > int const * ip = b.ip();


    > Alternatively, some trickery using casts would do.


    > BTW: why would you want the const method invoked?


    That's a bit longer story: The array in the class will be an
    array of pointers to rather large amounts of data. And I will
    need lots of copies of that class. In the copies typically
    only small subsets of the data will have to be changed. Thus,
    to keep the total amount of memory used down, my idea was to
    have boost::shared_ptr's in the array (thus having a refe-
    rence count and automatic deallocation) and to make a "real"
    copy of an element only when it is needed, i.e. when a non-
    const instance of the element is requested and the reference
    count isn't 1. For that I had hoped for the function for re-
    turning a const reference/pointer to be invoked when a const
    reference/pointer is requested and the non-const returning
    version otherwise (in which then a copy is made when neces-
    sary). And then, of course, I hoped to make all that com-
    pletely transparent to the user of the class, so they don't
    have to think too much about what they're doing...

    > > I also noticed the same
    > > effect when using const versus non-const references as return
    > > values, also there the non-const returning function is called
    > > eben when one asks for a const reference. Does all this only
    > > work when overloading the [] operator?


    > The operator[] is not different: the const version is called on const
    > objects and the non-const version is called on non-const objects. So it is
    > not clear, what you observed.


    Probably my observations weren't very good. to be honest at
    the moment I'm still a bit overloaded with understanding
    what is happening when;-) But your explanation has hopefully
    cleared up a few misconceptions.

    Best regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, May 25, 2010
    #6
  7. Saeed Amrollahi <> wrote:
    > On May 25, 10:03 pm, (Jens Thoms Toerring) wrote:
    > > Hi,
    > >
    > >   I am rather new to C++ and have run into a problem where I
    > > haven't found an answer yet by searching (probably didn't find
    > > the right search terms). I Have this simple program:
    > >
    > > #include <iostream>
    > >
    > > class A
    > > {
    > >   public:
    > >     A( int i ) : m_ip( new int[ i ] ) { }
    > >     int const * ip( ) const { std::cout << "const\n"; return m_ip; }
    > >     int * ip( ) const { std::cerr << "non-const\n"; return m_ip; }
    > >
    > >   private:
    > >     int * m_ip;
    > >
    > > };
    > >
    > > int main( )
    > > {
    > >     A a( 10 );
    > >     int const * ip = a.ip( );
    > >     std::cout << ip[ 2 ] << '\n';
    > >
    > > }
    > >
    > > My exectation was that when calling ip() to get a const pointer
    > > the compiler would be able to figure out I want it to use the
    > > first ip() method that returns a const pointer. But it turns out
    > > that always the second one is invoked. I'm not sure why and if
    > > there's a way that I can make it pick the second one (short of
    > > using different names for the methods)? I also noticed the same
    > > effect when using const versus non-const references as return
    > > values, also there the non-const returning function is called
    > > eben when one asks for a const reference. Does all this only
    > > work when overloading the [] operator?
    > >
    > >                             Best regards, Jens
    > > --
    > >   \   Jens Thoms Toerring  ___      
    > >    \__________________________      http://toerring.de


    > Hi Jens


    > At first your code doesn't work. You can't overload
    > a function just base on different return type.
    > I guess your ip member functions should be like this:
    > int const * ip( ) const { std::cout << "const\n"; return m_ip; }
    > int * ip( ) { std::cerr << "non-const\n"; return m_ip; }


    Yes, exactly - obviously a gone-wrong last minute change
    before pasting it into my post. Won't happen again if I
    can avoid it.

    > Second, if you allocate memory in construtor,
    > you must free it in destructor:
    > A( int i ) : m_ip( new int) { } // new an array
    > ~A() { delete [] ip; } // delete the array
    > Third, You didn't initialize your array. Constructor
    > is the best way for initialization. For example:
    > A( int i ) : m_ip( new int[ i ] )
    > {
    > std::fill(m_ip, m_ip + i, 0);
    > }


    Yes, had snipped all that parts since I wanted to example
    as short as possible.

    > about your question:
    > the const member function means
    > 1. You don't want to change the state of object via it
    > 2. For const object, just const member function should be called.
    > It is the obvious result of #1


    I hadn't been aware that the const-returning function would
    only be invoked for a const object but laboured under the
    wrong impression that what I assign it to would make a dif-
    ference. I hope I will keep that in mind in the future;-)

    > See the following code:
    > A a( 10 );
    > int const * ip = a.ip();
    > ip[0]++; // error *ip is const;
    > int* ip2 = a.ip();
    > ip2[1]++; // OK: *ip2 is not const
    > const A a2(20);
    > a2.ip(); // calling const ip


    Yes, I see.
    Thanks and best regards, Jens

    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, May 25, 2010
    #7
  8. Jens Thoms Toerring

    Kai-Uwe Bux Guest

    Jens Thoms Toerring wrote:

    > Kai-Uwe Bux <> wrote:
    >> Jens Thoms Toerring wrote:
    >> > I am rather new to C++ and have run into a problem where I
    >> > haven't found an answer yet by searching (probably didn't find
    >> > the right search terms). I Have this simple program:
    >> >
    >> > #include <iostream>
    >> >
    >> > class A
    >> > {
    >> > public:
    >> > A( int i ) : m_ip( new int[ i ] ) { }
    >> > int const * ip( ) const { std::cout << "const\n"; return m_ip; }

    > ^^^^^
    > Sorry, that was a mistake just before copy-and-paste...
    >
    >> > int * ip( ) const { std::cerr << "non-const\n"; return m_ip; }
    >> >
    >> > private:
    >> > int * m_ip;
    >> > };
    >> >
    >> > int main( )
    >> > {
    >> > A a( 10 );
    >> > int const * ip = a.ip( );
    >> > std::cout << ip[ 2 ] << '\n';
    >> > }


    [...]
    >> > I'm not sure why and if
    >> > there's a way that I can make it pick the second one (short of
    >> > using different names for the methods)?

    >
    >> Yes, you could do:

    >
    >> A a ( 10 );
    >> A const & b ( a ); // be is a const alias for the object a.
    >> int const * ip = b.ip();

    >
    >> Alternatively, some trickery using casts would do.

    >
    >> BTW: why would you want the const method invoked?

    >
    > That's a bit longer story: The array in the class will be an
    > array of pointers to rather large amounts of data. And I will
    > need lots of copies of that class. In the copies typically
    > only small subsets of the data will have to be changed. Thus,
    > to keep the total amount of memory used down, my idea was to
    > have boost::shared_ptr's in the array (thus having a refe-
    > rence count and automatic deallocation) and to make a "real"
    > copy of an element only when it is needed, i.e. when a non-
    > const instance of the element is requested and the reference
    > count isn't 1. For that I had hoped for the function for re-
    > turning a const reference/pointer to be invoked when a const
    > reference/pointer is requested and the non-const returning
    > version otherwise (in which then a copy is made when neces-
    > sary). And then, of course, I hoped to make all that com-
    > pletely transparent to the user of the class, so they don't
    > have to think too much about what they're doing...


    I see: you want copy-on-write. The problem is _where_ and _how_ the copy-on-
    write should be handled. It is somewhat tricky to use COW with classes that
    have not been designed with that in mind. Your options include:

    a) If you control the classes that your container should contain, then have
    them handle the COW transparently and just use std::vector (or some other
    container type from STL) as the container. The copy will be made
    transparently when a non-const member function on the retreived object is
    invoked.

    b) Change the interface of the container so that you don't rely on
    "overloading via return type". E.g.: have different names for functions
    returning const references or do something like:

    void get_ptr ( T const * & p_ref, size_type index );
    void get_ptr ( T * & p_ref, size_type index );


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, May 25, 2010
    #8
  9. Jens Thoms Toerring

    James Kanze Guest

    On May 25, 9:10 pm, Kai-Uwe Bux <> wrote:
    > Jens Thoms Toerring wrote:
    > > Kai-Uwe Bux <> wrote:
    > >> Jens Thoms Toerring wrote:
    > >> > I am rather new to C++ and have run into a problem where I
    > >> > haven't found an answer yet by searching (probably didn't find
    > >> > the right search terms). I Have this simple program:


    > >> > #include <iostream>


    > >> > class A
    > >> > {
    > >> > public:
    > >> > A( int i ) : m_ip( new int[ i ] ) { }
    > >> > int const * ip( ) const { std::cout << "const\n"; return m_ip; }

    > > ^^^^^
    > > Sorry, that was a mistake just before copy-and-paste...


    > >> > int * ip( ) const { std::cerr << "non-const\n"; return m_ip; }


    > >> > private:
    > >> > int * m_ip;
    > >> > };


    > >> > int main( )
    > >> > {
    > >> > A a( 10 );
    > >> > int const * ip = a.ip( );
    > >> > std::cout << ip[ 2 ] << '\n';
    > >> > }


    > [...]


    > >> > I'm not sure why and if there's a way that I can make it
    > >> > pick the second one (short of using different names for
    > >> > the methods)?


    > >> Yes, you could do:


    > >> A a ( 10 );
    > >> A const & b ( a ); // be is a const alias for the object a.
    > >> int const * ip = b.ip();


    That's awkward. And if the goal is to have different behavior
    depending on what the client code does with the results, it's
    very error prone, even supposing you control all of the client
    code.

    > >> Alternatively, some trickery using casts would do.


    > >> BTW: why would you want the const method invoked?


    > > That's a bit longer story: The array in the class will be an
    > > array of pointers to rather large amounts of data. And I
    > > will need lots of copies of that class. In the copies
    > > typically only small subsets of the data will have to be
    > > changed. Thus, to keep the total amount of memory used down,
    > > my idea was to have boost::shared_ptr's in the array (thus
    > > having a refe- rence count and automatic deallocation) and
    > > to make a "real" copy of an element only when it is needed,
    > > i.e. when a non- const instance of the element is requested
    > > and the reference count isn't 1. For that I had hoped for
    > > the function for re- turning a const reference/pointer to be
    > > invoked when a const reference/pointer is requested and the
    > > non-const returning version otherwise (in which then a copy
    > > is made when neces- sary). And then, of course, I hoped to
    > > make all that com- pletely transparent to the user of the
    > > class, so they don't have to think too much about what
    > > they're doing...


    > I see: you want copy-on-write. The problem is _where_ and
    > _how_ the copy-on- write should be handled. It is somewhat
    > tricky to use COW with classes that have not been designed
    > with that in mind. Your options include:


    > a) If you control the classes that your container should
    > contain, then have them handle the COW transparently and just
    > use std::vector (or some other container type from STL) as the
    > container. The copy will be made transparently when a
    > non-const member function on the retreived object is invoked.


    > b) Change the interface of the container so that you don't
    > rely on "overloading via return type". E.g.: have different
    > names for functions returning const references or do something
    > like:


    > void get_ptr ( T const * & p_ref, size_type index );
    > void get_ptr ( T * & p_ref, size_type index );


    The usual solution in such cases is to return a proxy class, so
    that you can effectively overload on what the client code does
    with the object.

    --
    James Kanze
    James Kanze, May 25, 2010
    #9
  10. Jens Thoms Toerring

    Kai-Uwe Bux Guest

    James Kanze wrote:

    > On May 25, 9:10 pm, Kai-Uwe Bux <> wrote:
    >> Jens Thoms Toerring wrote:
    >> > Kai-Uwe Bux <> wrote:
    >> >> Jens Thoms Toerring wrote:

    [...]
    >> > That's a bit longer story: The array in the class will be an
    >> > array of pointers to rather large amounts of data. And I
    >> > will need lots of copies of that class. In the copies
    >> > typically only small subsets of the data will have to be
    >> > changed. Thus, to keep the total amount of memory used down,
    >> > my idea was to have boost::shared_ptr's in the array (thus
    >> > having a refe- rence count and automatic deallocation) and
    >> > to make a "real" copy of an element only when it is needed,
    >> > i.e. when a non- const instance of the element is requested
    >> > and the reference count isn't 1. For that I had hoped for
    >> > the function for re- turning a const reference/pointer to be
    >> > invoked when a const reference/pointer is requested and the
    >> > non-const returning version otherwise (in which then a copy
    >> > is made when neces- sary). And then, of course, I hoped to
    >> > make all that com- pletely transparent to the user of the
    >> > class, so they don't have to think too much about what
    >> > they're doing...

    >
    >> I see: you want copy-on-write. The problem is _where_ and
    >> _how_ the copy-on- write should be handled. It is somewhat
    >> tricky to use COW with classes that have not been designed
    >> with that in mind. Your options include:

    >
    >> a) If you control the classes that your container should
    >> contain, then have them handle the COW transparently and just
    >> use std::vector (or some other container type from STL) as the
    >> container. The copy will be made transparently when a
    >> non-const member function on the retreived object is invoked.

    >
    >> b) Change the interface of the container so that you don't
    >> rely on "overloading via return type". E.g.: have different
    >> names for functions returning const references or do something
    >> like:

    >
    >> void get_ptr ( T const * & p_ref, size_type index );
    >> void get_ptr ( T * & p_ref, size_type index );

    >
    > The usual solution in such cases is to return a proxy class, so
    > that you can effectively overload on what the client code does
    > with the object.


    In my experience, that proxy class tends to grow over time and in the end it
    forwards all member functions of the underlying class to make informed and
    well-suited decisions on whether to copy or not. Effectively, one writes a
    wrapper that essentially reproduces option (a).

    Of course, if we could overload the dot-operator ... <g>


    However, you are correct: I missed that option, which I should have
    mentioned.


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, May 25, 2010
    #10
  11. Kai-Uwe Bux <> wrote:
    > James Kanze wrote:
    > > On May 25, 9:10 pm, Kai-Uwe Bux <> wrote:
    > >> Jens Thoms Toerring wrote:
    > >> > Kai-Uwe Bux <> wrote:


    > >> I see: you want copy-on-write.


    Yes.

    > The problem is _where_ and
    > >> _how_ the copy-on- write should be handled.


    Yes, exactly;-)

    > It is somewhat
    > >> tricky to use COW with classes that have not been designed
    > >> with that in mind. Your options include:

    > >
    > >> a) If you control the classes that your container should
    > >> contain, then have them handle the COW transparently and just
    > >> use std::vector (or some other container type from STL) as the
    > >> container. The copy will be made transparently when a
    > >> non-const member function on the retreived object is invoked.

    > >
    > >> b) Change the interface of the container so that you don't
    > >> rely on "overloading via return type". E.g.: have different
    > >> names for functions returning const references or do something
    > >> like:

    > >
    > >> void get_ptr ( T const * & p_ref, size_type index );
    > >> void get_ptr ( T * & p_ref, size_type index );

    > >
    > > The usual solution in such cases is to return a proxy class, so
    > > that you can effectively overload on what the client code does
    > > with the object.


    > In my experience, that proxy class tends to grow over time and in the end it
    > forwards all member functions of the underlying class to make informed and
    > well-suited decisions on whether to copy or not. Effectively, one writes a
    > wrapper that essentially reproduces option (a).


    > Of course, if we could overload the dot-operator ... <g>


    Thanks, you gave me quite a number of new ideas I have to read
    up upon and think about...
    Best regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, May 25, 2010
    #11
  12. Jens Thoms Toerring

    John H. Guest

    Jens Thoms Toerring wrote:
    > I hadn't been aware that the const-returning function would
    > only be invoked for a const object but laboured under the
    > wrong impression that what I assign it to would make a dif-
    > ference. I hope I will keep that in mind in the future;-)


    Just to summarize:
    - Non-const objects can call their non-const or const functions. If
    the function being called is overloaded with both a const and a non-
    const version, then non-const objects will call their non-const
    version.
    - const objects can call their const functions.
    John H., May 26, 2010
    #12
    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. coala
    Replies:
    3
    Views:
    372
    coala
    Sep 6, 2006
  2. Replies:
    4
    Views:
    269
    Mark P
    Nov 7, 2006
  3. Javier
    Replies:
    2
    Views:
    559
    James Kanze
    Sep 4, 2007
  4. fungus
    Replies:
    13
    Views:
    886
    fungus
    Oct 31, 2008
  5. Old Wolf

    Same pointer parameter const and non-const

    Old Wolf, Nov 3, 2009, in forum: C Programming
    Replies:
    3
    Views:
    534
    Ben Bacarisse
    Nov 4, 2009
Loading...

Share This Page