
template<class T> class shared_ptr { template<class Y> explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { detail::sp_enable_shared_from_this( pn, p, p ); } }; I've tried really hard to figure out what it means when a constructor is both a template as well as explicit. The keywords have incompatible meanings to me and therefore I fail to make sense of it. If you template the argument, then you're saying you'll accept any type of pointer as long as it will still compile, and the explicit implies no explicit conversions to Y, which shouldn't happen anyway due to the template indicating any argument is valid as long as it complies. I googled for this and researched the C++ Templates book without success. Also, nobody I've asked this about could give me a satisfactory answer, and so I'm hoping somebody on the boost list won't mind enlightening me by providing a few concrete examples where it comes into play. And I apologize for wasting everybody else's time with this. Thanks, -Sid

On Monday 19 November 2007 22:11:37 Sid Sacek wrote:
template<class T> class shared_ptr { template<class Y> explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { detail::sp_enable_shared_from_this( pn, p, p ); } };
I've tried really hard to figure out what it means when a constructor is both a template as well as explicit. The keywords have incompatible meanings to me and therefore I fail to make sense of it. If you template the argument, then you're saying you'll accept any type of pointer as long as it will still compile, and the explicit implies no explicit conversions to Y, which shouldn't happen anyway due to the template indicating any argument is valid as long as it complies.
To be honest, I don't know, but did you try to remove the explicit? You don't have to recreate/copy the whole shared_ptr class to see it: struct test { test(); test(test const&); template<typename T> explicit test(T* p); }; void function(test t); int main() { void* p; function(p); } I'd say this is equivalent, only that test is not a class template. Now, if you remove the 'explicit', it suddenly compiles.
I googled for this and researched the C++ Templates book without success. Also, nobody I've asked this about could give me a satisfactory answer, and so I'm hoping somebody on the boost list won't mind enlightening me by providing a few concrete examples where it comes into play.
I'd say this is a general C++ question and thus not really the goal of the mailinglist. I'd suggest you ask the question in the Usenet, in comp.lang.c++.moderated to be precise. Typically you get very good answers there. Uli

Assume you have this: void some_func(shared_ptr<some_class> p); some_class * ptr = ...; some_func(ptr); Would you really want an automatic conversion of ptr to shared_ptr<some_class> ? Best, John
template<class T> class shared_ptr { template<class Y> explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { detail::sp_enable_shared_from_this( pn, p, p ); } };
-- http://John.Torjo.com -- C++ expert ... call me only if you want things done right

Sid Sacek wrote:
template<class T> class shared_ptr { template<class Y> explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { detail::sp_enable_shared_from_this( pn, p, p ); } };
I've tried really hard to figure out what it means when a constructor is both a template as well as explicit. The keywords have incompatible meanings to me and therefore I fail to make sense of it. If you template the argument, then you're saying you'll accept any type of pointer as long as it will still compile, and the explicit implies no explicit conversions to Y, which shouldn't happen anyway due to the template indicating any argument is valid as long as it complies.
You're incorrect on the second restriction. It doesn't mean "no explicit conversions to Y", it means "no implicit conversions from Y to shared_ptr<T>". So as long as you use explicit construction, like this: shared_ptr<A> myPtr(x); you can use any 'x' that is implicitly convertible to an 'A *'. -- Jon Biggar Levanta jon@levanta.com 650-403-7252

Sid Sacek wrote:
template<class T> class shared_ptr { template<class Y> explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { detail::sp_enable_shared_from_this( pn, p, p ); } };
I've tried really hard to figure out what it means when a constructor is both a template as well as explicit.
shared_ptr's constructor is explicit because its interface is not very safe. It takes ownership of the passed pointer, so that's why you must be sure that's really what you want to do. Other smart pointers have similar behaviours. There would be no need for it to be explicit if shared_ptr took in-place factories instead, or even objects it would copy or move, like any normal container.
participants (5)
-
John Torjo
-
Jonathan Biggar
-
Mathias Gaunard
-
Sid Sacek
-
Ulrich Eckhardt