Boost logo

Boost Users :

Subject: Re: [Boost-users] [shared_ptr] Error in Constructor
From: David Greene (greened_at_[hidden])
Date: 2010-05-22 13:33:12


On Saturday 22 May 2010 04:14:38 Peter Dimov wrote:

> > Urk. I just found out. The attached test does not compile with
> > BOOST_SP_NO_SP_CONVERTIBLE because it renders shared_ptr
> > unable to construct pointer-to-base from pointer-to-derived.
>
> I see why your original test doesn't compile, but I don't see why this one
> should not. The only error I get with g++ is
>
> testbed.cpp:33: error: operands to ?: have different types
> `boost::shared_ptr<Base>' and `boost::shared_ptr<A>'

Well, yes. Without BOOST_SP_NO_SP_CONVERTIBLE, the test does not
generate that error. If the code used bare pointers the error would
also not occur, so it's surprising to see it just by using a smart pointer.

> and when I insert a conversion to shared_ptr<Base> to make them the same
> type, it compiles.

True. But again, the cast isn't needed with bare pointers.

> Defining BOOST_SP_NO_SP_CONVERTIBLE will break other cases such as
>
> void foo( shared_ptr<Base> );
> void foo( shared_ptr<int> ); // 'int' stands for an unrelated type
>
> and then calling foo with shared_ptr<A>. A similar scenario occurs if in
> your original example the functions are changed to take shared_ptr<const
> Wrapper<A>> and shared_ptr<const Wrapper<B>>, respectively.

Right, because there is no exact match so conversions must be tried.
I was surprised in the first test that the compiler would even bother
instantiating other classes when there is an exact match to a function
signature. Does the standard require the compiler to try all conversions
even when there is an exact match?

Ah, answered right below!

> FWIW, I believe that you original example can be rejected by a compiler
> even with BOOST_SP_NO_SP_CONVERTIBLE defined. I don't think that the
> compiler is required to short-circuit overload resolution when it sees an
> exact match. It may well proceed to instantiate shared_ptr<Wrapper<A>> in
> order to see whether the argument can be converted to it (even though it's
> clear at this point that the conversion sequence will contain a
> user-defined conversion).

That's really bad. It effectively means one can't easily tell when one might
need the full definition of a type. I ran into this because I wanted to
decouple some code defining the body of one function that takes one
type from the body of another that takes a different type. In terms of
the example, I didn't want changes to A to cause recompilation of
functions that take a Wrapper<B>.

Requiring A to be defined everywhere B is used when there happens to
be a declaration of a function that takes A (as with member functions)
is less than friendly behavior. It seems worth it to clarify in the standard,
making it explicit that the code should compile, even without
BOOST_SP_NO_SP_CONVERTIBLE. In other words, my expectation would
be to have overload resolution short-circuited by exact matches. I don't
think having the failed instantiation of A fall under SFINAE would work
because behavior would change based on whether or not the definition
of A is available.

                                                -Dave


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net