Search code examples
c++c++11shared-ptrweak-ptr

weak_ptr's weird copy constructors


the following are 2 of weak_ptr's constructors: http://msdn.microsoft.com/en-us/library/bb982126.aspx

weak_ptr(const weak_ptr&);

template<class Other>
weak_ptr(const weak_ptr<Other>&);

actual code (from memory):

weak_ptr(const weak_ptr& _Other)
{   // construct weak_ptr object for resource pointed to by _Other
    this->_Resetw(_Other);
}

template<class _Ty2>
weak_ptr(const weak_ptr<_Ty2>& _Other,
         typename enable_if<is_convertible<_Ty2 *, _Ty *>::value,
         void *>::type * = 0)
{   // construct weak_ptr object for resource pointed to by _Other
    this->_Resetw(_Other);
}

Q1: Why is the top copy constructor even there? It looks like the bottom one accounts for every case (including the top one). Does it even get called? and if they didn't include it would the bottom one take it's place?

Q2: What's going on with the second argument of the bottom (templated) constructor. I think I understand the SFINAE aspect, but I don't understand why there is an extra * after ::type


Solution

  • Q1) If you don't write a copy constructor, the compiler will generate one for you, which wouldn't be what you want. Templated conversion constructors don't count.

    Q2) Remember that shared_ptr<T> is like a T*, convertibility must be checked at the level of pointers. If T* is convertible to U* then you should be able to assign one to the other. Think of pointers-to-base. [Sorry, that wasn't what you asked.] The final argument type just needs to exist, but also we don't want to have to specify the argument itself. A universal way of making up a type for which we can also provide a default argument is a pointer. In short, we need to make the function depend on a type that may or may not exist, but without actually requiring the user to know about this.