
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
and shared_ptr , 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
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