Rani, Here's what Steve Adamczyk (Mr. overload resolution) at EDG had to say about it:
I tracked down why we do what we do. It comes down to 13.3.3.1.2/4: 4 A conversion of an expression of class type to the same class type is given Exact Match rank, and a conversion of an expression of class type to a base class of that type is given Conversion rank, in spite of the fact that a copy constructor (i.e., a user-defined conversion function) is called for those cases. Now, the idea of using the auto_ptr kind of trick (copying by way of an auxiliary class) was not thought of when this paragraph was done, but the point was that for purposes of overload resolution copying X to X is always an exact match even if something is called to do the copy. Now, we could do a core issue to find out what this paragraph means for the auto_ptr kind of case. I have to say, though, that it would be an expensive thing to have to check everywhere that a copy that looks like an exact match is done, and there's nothing that says that calling a conversion function and copy constructor is less efficient than calling a copy constructor, so I'd be inclined to say that it should just be clarified to say that such a copy is considered an exact match regardless of the actual mechanism used to perform the copy. Steve ----- Rani wrote this ---- Interesting challenge (at least for me). In first glance it seems to be impossible which made it even more interesting. typedef char (&yes)[1]; typedef char (&no) [2]; // // TODO: handle types that can't be members // (e.g. void, abstract, functions) // template<class T> struct has_regular_ctor { private: struct ctor_tester { T t; struct B {}; operator B() const; ctor_tester(B); private: // VC warnings ctor_tester& operator=(ctor_tester const&); }; static yes check(ctor_tester, int); template<typename U> static no check(ctor_tester const&, U); static ctor_tester const& get(); public: static const bool value = sizeof(check(get(), 0)) == sizeof(yes); }; struct A1 { A1(A1&); }; struct A2 { A2(A2 const&); }; typedef char test[!has_regular_ctor<A1>::value]; typedef char test[!has_regular_ctor<A1 const>::value]; typedef char test[ has_regular_ctor<A2>::value]; typedef char test[ has_regular_ctor<A2 const>::value]; typedef char test[ has_regular_ctor<int>::value]; The above code compiled fine with VC7.1 beta but failed to compile using EDG and GCC. Here is an explanation for why I think that it's compliant: The form of the ctor of ctor_tester is the same as its member t (12.8/5). In case the ctor argument has const qualifier then both check functions has an exact match (13.3.3.1.1/3), the first check using Lvalue-transformation and the second using identity. The ambiguity buster in this case is the non-template function. In case that the ctor is not const then the first version is viable using user defined conversion sequence (like auto_ptr: ctor_tester -> B) and the second is still identity. Overloading is so complex that I have doubts and I'll be happy to ear a second opinion. Rani -- Dave Abrahams Boost Consulting www.boost-consulting.com _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost