Re: Deep const-ness in array of pointers?
 
spacewrench wrote:
I'd like to give an array of pointers to a class instance, and let
the instance return references (either const or mutable) to the
array elements.  However, when I return a const reference to one of
the pointers, I can still modify the pointed-to object through the
pointer (I just can't change to pointer to point to a different
object). Instead, I'd like to have the const-ness "trickle down,"
so that if I return a const pointer, it's actually a const * const.
 (This is a poor English description of the following code.)  I'm
using g++-4.3.2, and it warns about returning a reference to a
temporary in whynot(). I don't understand why a temporary must be
created in this situation. Is it a g++ anomaly, or is there a
sneaky problem with what I'm trying to do? 
[snip code -- situation is summarized in code example below]
This question came up a couple of weeks ago, but nobody answered it
sufficiently, as far as I can tell (it seems my point was too subtle).
I'm thinking that for whatever reason, the standard requires that a
temporary be created in the reference case, even though in the
equivalent pointer situation none is required. Here's the issue boiled
down to the essential:
    int main()
    {
        int i;
        int* t = &i;
        
        // Address of t, so pointer is bound directly
        const int* const* p = &t; // see C++03 section 4.4 paragraph 4
        if ( p == &t )
            cout << "p == &t\n";
        
        // Bound to dereferenced p, so also bound directly, even
        // though the type differs (in cv qualifiers) from t
        const int* const& r = *p;
        if ( &r == &t )
            cout << "&r == &t\n";
        
        // Bound to temporary?!? Even though it's same type as r, and
        // above shows that it could be bound directly to t, it's not.
        const int* const& s = t;
        if ( &s != &t )
            cout << "&s != &t\n";
    }
As you can see, you can get the behavior you want, but you must first
convert it to a pointer to T, then take a reference to that
dereferenced pointer. So in your original example:
    class Bar {
    [...]
        const Foo * const & whynot( unsigned n ) const
        {
            // return arrayOfFoo [n]; // won't work
            const Foo * const * t = &arrayOfFoo [n]; // take address
            return *t; // dereference (NOT bound to temporary either!)
        }
    
      private:
        Foo * * const arrayOfFoo;
    } ;
Here's a link to the thread  from a few weeks ago (news and web links):
<news:89b13820-a299-44d3-9b56-e77619d01d80@35g2000pry.googlegroups.com>
<http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/2fde5681cab049b5/075f8a5f38492197>