Reputation: 9784
This is with XCode C++ language dialect c++1y. Help me understand unique_ptr:
//1
auto ouput2 = make_unique<standard::Algorithm>(AlgorithmFactory::create("YamlOutput",
"filename", outputFilename));
//2
unique_ptr<standard::Algorithm> output(standard::AlgorithmFactory::create("YamlOutput",
"filename", outputFilename));
1 fails with build with "Semantic Issue: Allocating an object of abstract class type 'essentia::standard::Algorithm", but 2 succeeds.
I read that these two are equivalent, so how come one succeeds and the other doesn't?
I look at the source for AlgorithmFactory::create() it returns a BaseAlgorithm* depending on the string input. Not really understanding the object hierarchy since standard::Algorithm doesn't seem to have anything to do with BaseAlgorithm (it doesn't extend it).
This is how the documentation for the Essentia library I am using did it except they were using a naked pointer.
Upvotes: 1
Views: 344
Reputation: 45665
The two statements aren't equivalent. The difference is:
Your second version is calling the unique_ptr
constructor by providing an existing raw pointer to the object. It only encapsulates that object pointer in a unique_ptr
.
The first version is supposed to be provided with the constructor arguments for your object, and it will create the object for you in a safe way. It both constructs and encapsulates an object in a unique_ptr
.
The problem is that your factory already allocates the object and returns a raw pointer to it. At that point it doesn't make sense anymore to use make_unique
since the purpose of that function is to avoid dealing with raw pointers completely, i.e. construct-and-wrap in one go.
You have two options here:
Stick to your second version.
Change the factory such that it returns a unique_ptr
by using make_unique
in its implementation. But it could make sense to also provide a shared_ptr
-version of the same factory. Something like createUnique
+ createShared
, and maybe keep the existing create
which returns a raw pointer. That's a question of code style however.
Upvotes: 3
Reputation: 119059
std::make_unique<T>
forwards its arguments to T
's constructor and constructs a new T
, then makes a std::unique_ptr<T>
that points to the newly constructed T
. If T
is an abstract class then this will definitely fail. Even if T
were not an abstract class, this would likely not compile since the AlgorithmFactory::create
function presumably returns a T*
. On the other hand, std::unique_ptr<T>
's constructor takes an argument convertible to T*
, and there is no problem.
Upvotes: 1
Reputation: 41213
They aren't equivalent. make_unique
creates the object whereas unique_ptr
simply wraps an existing pointer.
Your first line is equivalent to unique_ptr<standard::Algorithm>(new standard::Algorithm(AlgorithmFactory::create(...)))
. Note the usage of new
here.
Upvotes: 4