Re: Smart pointers of const objets

From: tom_usenet (tom_usenet_at_hotmail.com)
Date: 10/29/03


Date: Wed, 29 Oct 2003 10:20:28 +0000

On 28 Oct 2003 19:44:42 -0800, gao_bolin@voila.fr (Bolin) wrote:

>tom_usenet <tom_usenet@hotmail.com> wrote in message news:<1cispvofogid0vh0fr1euchsjq16v2vbcb@4ax.com>...
>>
>> void foo(boost::shared_ptr<A const> a)
>> or
>> void foo(boost::shared_ptr<A const> const& a)
>>
>> You shouldn't pass "pointers" by reference though, since it disables
>> conversions (for reasons that should be fairly obvious).
>
>I am not sure to get that last sentence -- probably not obvious for
>people like me. Plus, I always thought it was a bad idea to pass an
>object. A smart smart pointer might contain much more than just a
>pointer. Besides, references to pointers are used in boost's examples
>illustrating the use of smart pointers (e.g. in
>shared_ptr_example.cpp).

The problem is that you cannot bind a temporary object to a non-const
reference. You can only bind an lvalue (usually a named variable of
the matching type) to a non-const reference. Here we have a variable
of type
shared_ptr<A>
and you are trying to bind it to a reference
shared_ptr<A const>&
Now, there is a conversion from shared_ptr<A> to shared_ptr<A const>,
but this introduces a temporary object, which will not bind to the
non-const reference. It will bind to a const reference though:
shared_ptr<A const> const&
since that conversion isn't considered dangerous since you can't
modify the bound temporary. I can't find anything in the faq about
this unfortunately.

>> You can't bind a temporary to a non-const reference. Things like
>> pointers and iterators should not be passed by non-const reference
>> unless you intend to change the original value. Obviously, to change
>> the original value, you have to pass an lvalue of the correct type to
>> the function in question.
>
>Is a temporary created when passing by reference? I thought no.

For shared_ptr, yes. shared_ptr has a templated copy constructor that
enables the conversions. Your conversion technique is actually
illegal:
operator Ptr<const T> & ()
{
  return *(static_cast<Ptr<const T>*>(static_cast<void*>(this)));
}
since you aren't allowed to static (or reinterpret) cast between
unrelated types - Ptr<const T> and Ptr<T> are unrelated types (they
aren't related by inheritence). shared_ptr's (legal) technique is to
add a converting constructor:

template <class U>
shared_ptr(shared_ptr<U> const& other);

That can convert any shared_ptr<T> to any shared_ptr<U> where T*
converts to U*. T* converts to T const* so that is how the conversion
is done, by creating a new shared_ptr<T const>.

 A cout
>in the class constructor do not produce any output when calling foo(A
>&a). Should a temporary be created in theory?

The temporary comes from the conversion. You can of course bind an
object directly to a reference if it is the exact type of a sub type
of the reference type.

ostream& os = cout; //direct binding
shared_ptr<T> p;
shared_ptr<T>& pref = p; //direct binding
shared_ptr<T const>& pcref = p; //illegal, requires a temporary

>Again, I am not sure what is illegal here. Besides, the code compiles.

Not on my standards compliant compilers! What compiler are you using?

MSVC7.1 (strict mode):
extra.cpp(9) : error C2664: 'f' : cannot convert parameter 1 from 'int
*' to 'const int *& '
        Conversion loses qualifiers

Comeau C++ 4.3:
"main.cpp", line 9: error: a reference of type "const int *&" (not
          const-qualified) cannot be initialized with a value of type
"int *"
    f(p);
      ^
It has always been illegal in standard C++ to bind a temporary (in
this case a temporary int const*) to a non const reference. IIRC, MS
compilers allow the conversion in non-strict mode for backwards
compatibility with their pre-standard C++ compilers.

See e.g.
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=KANZE.96Mar29121910%40gabi.gabi-soft.fr

Tom



Relevant Pages

  • Re: REFERENCES REVEALED
    ... >> From the practical point of view there is the fact that a const ... >> reference can bind to a temporary, ... This is Undefined Behavior. ...
    (comp.lang.cpp)
  • Re: how to initialise a reference in g++
    ... I've never seen a const temporary. ... Temporaries: ... >> You cannot bind a reference to a temporary... ...
    (comp.lang.cpp)
  • Re: Returning by value, returning by reference
    ... > int ReturnValue ... > You can bind a temporary returned from a function to a reference. ... A function that returns a const reference. ...
    (comp.lang.cpp)
  • Re: Anders Hejlsberg comment on immutable objects
    ... >>explicit interface implementation exists is so an interface name can ... I wouldn't cast to an ... >>Improper conversion sounds like a good description, ... > variable as a sort of implicit reference, ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Conversion Problems
    ... Remove the reference to dao2535.tlb. ... > I've also read LeAnne's answer to my Conversion Error question in this ... >> Doug Steele, Microsoft Access MVP ...
    (microsoft.public.access.gettingstarted)