925. shared_ptr's explicit conversion from unique_ptr

Section: 20.3.2.2.2 [util.smartptr.shared.const] Status: C++11 Submitter: Rodolfo Lima Opened: 2008-10-12 Last modified: 2016-01-28

Priority: Not Prioritized

View other active issues in [util.smartptr.shared.const].

View all other issues in [util.smartptr.shared.const].

View all issues with C++11 status.

Discussion:

The current working draft (N2798), section 20.3.2.2.2 [util.smartptr.shared.const] declares shared_ptr's constructor that takes a rvalue reference to unique_ptr and auto_ptr as being explicit, affecting several valid smart pointer use cases that would take advantage of this conversion being implicit, for example:

class A;
std::unique_ptr<A> create();
void process(std::shared_ptr<A> obj);

int main()
{
   process(create());                  // use case #1
   std::unique_ptr<A> uobj = create();
   process(std::move(uobj));           // use case #2
   return 0;
}

If unique_ptr to shared_ptr conversions are explicit, the above lines should be written:

process(std::shared_ptr<A>(create()));        // use case #1
process(std::shared_ptr<A>(std::move(uobj))); // use case #2

The extra cast required doesn't seems to give any benefits to the user, nor protects him of any unintended conversions, this being the raison d'etre of explicit constructors.

It seems that this constructor was made explicit to mimic the conversion from auto_ptr in pre-rvalue reference days, which accepts both lvalue and rvalue references. Although this decision was valid back then, C++0x allows the user to express in a clear and non verbose manner when he wants move semantics to be employed, be it implicitly (use case 1) or explicitly (use case 2).

[ Batavia (2009-05): ]

Howard and Alisdair like the motivating use cases and the proposed resolution.

Move to Tentatively Ready.

Proposed resolution:

In both 20.3.2.2 [util.smartptr.shared] paragraph 1 and 20.3.2.2.2 [util.smartptr.shared.const] change:

template <class Y> explicit shared_ptr(auto_ptr<Y> &&r);
template <class Y, class D> explicit shared_ptr(unique_ptr<Y, D> &&r);