Using C++11, let\'s say I have factory functions dealing with base and derived classes:
#include
using namespace std;
struct B { virtual ~B(
The compiler's behaviour is correct. There is only an implicit move when the types are the same, because implicit move is specified in terms of the compiler failing to perform copy elision in cases where it is actually allowed (see 12.8/31 and 12.8/32).
12.8/31 (copy elision):
in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type...
12.8/32 (implicit move):
When the criteria for elision of a copy operation are met, [...], overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.
With the addition of the std::move
calls in the return
statements, this code works for me on Visual Studio 2013:
#include <memory>
using namespace std;
struct B { virtual ~B() {} };
struct D : B {};
unique_ptr<B> MakeB()
{
auto b = unique_ptr<B>( new B() );
return std::move( b ); // *** std::move() added here! ***
}
unique_ptr<B> MakeD()
{
auto d = unique_ptr<D>( new D() );
return std::move( d ); // *** std::move() added here! ***
}
The following also works
unique_ptr<B> MakeB()
{
return unique_ptr<B>( new B() ); // *** Returning a temporary! ***
}
unique_ptr<B> MakeD()
{
return unique_ptr<D>( new D() ); // *** Returning a temporary! ***
}
Of course, if you're returning std::unique_ptr<B>
anyway, why not shove the D
instance into a std::unique_ptr<B>
in the first place? Then there's no conversion necessary at all!