Bug 53654 - move constructor incorrectly delete copy constructor defined by template
Summary: move constructor incorrectly delete copy constructor defined by template
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2012-06-13 08:03 UTC by Kirby Zhou
Modified: 2012-07-25 09:42 UTC (History)
1 user (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed:


Note You need to log in before you can comment on or make changes to this bug.
Description Kirby Zhou 2012-06-13 08:03:56 UTC
shared_ptr<T> declares its copy constructor and assign operator by template (if Y == T). But the nontrivial copy constructor is been deleted by the move constructor declaration.

template<class T>
struct shared_ptr
    template<class Y>
    shared_ptr( shared_ptr<Y> const & r );
    template<class Y>
    shared_ptr& operator=( shared_ptr<Y> && r );

    shared_ptr( shared_ptr<T> && r );
    shared_ptr& operator=( shared_ptr<T> && r );

struct TTransport {

struct TProtocol {
	shared_ptr<TTransport> func()
		return p_;
	shared_ptr<TTransport> p_;

]# g++47 -std=gnu++0x -c tshareptr.cpp 
tshareptr.cpp: In member function 'shared_ptr<TTransport> TProtocol::func()':
tshareptr.cpp:20:10: error: use of deleted function 'constexpr shared_ptr<TTransport>::shared_ptr(const shared_ptr<TTransport>&)'
tshareptr.cpp:3:8: note: 'constexpr shared_ptr<TTransport>::shared_ptr(const shared_ptr<TTransport>&)' is implicitly declared as deleted because 'shared_ptr<TTransport>' declares a move constructor or move assignment operator

declare a separate copy constructor individually.
Comment 1 Jonathan Wakely 2012-06-13 08:48:44 UTC
This behaviour is correct and required by the standard.

The template constructor is not a copy constructor, so a copy constructor is still implicitly-declared and defined as deleted. The standard says [class.copy]/2 "A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default values."

Your workaround is necessary (and exactly that change has been made to GCC's own shared_ptr)

      shared_ptr(const shared_ptr&) noexcept = default;
Comment 2 Paolo Carlini 2012-07-25 09:42:49 UTC
Let's close this, then.