Reputation: 2148
If I do:
std::unique_ptr<AVFrame, AVFrameDeleter> avFrameUniquePtr(av_frame_alloc());
I get no errors. Observe that
av_frame_alloc()
returns AVFrame*
However if I do
std::unique_ptr<AVFrame, AVFrameDeleter> avFrameUniquePtr = std::make_unique<AVFrame,AVFrameDeleter>(av_frame_alloc());
I get
no instance of overloaded function "std::make_unique" matches the argument list -- argument types are: (AVFrame *)
For me it should be ok. What's happening?
Upvotes: 2
Views: 3041
Reputation: 61910
make_unique
is for allocating an object (forwarding its arguments through to the constructor) and returning a unique_ptr
to that object. Since av_frame_alloc
already allocates the object, there's no reason to allocate again.
What you want is exactly what the constructor of unique_ptr
does—to take ownership of that pointer returned by av_frame_alloc
. make_unique
isn't the right tool for when you want to transfer ownership.
Now you mention in a comment that this is a class member. You can deal with that through braces (the language disallows parentheses in this context specifically) or the member initializer list of the constructors:
class Foo {
// A
std::unique_ptr<AVFrame, AVFrameDeleter> avFrameUniquePtr{av_frame_alloc()};
// B
std::unique_ptr<AVFrame, AVFrameDeleter> avFrameUniquePtr;
Foo() : avFrameUniquePtr(av_frame_alloc()) {}
};
Upvotes: 3
Reputation: 172924
What's happening?
Unfortunately, std::make_unique
can't specify the deleter type. Its 2nd template parameter is used for the type of the list of arguments passed to it. The code fails because you specify it as AVFrameDeleter
explicitly, but pass AVFrame*
, they don't match.
Unlike
std::make_shared
(which hasstd::allocate_shared
),std::make_unique
does not have an allocator-aware counterpart. A hypothetical allocate_unique would be required to invent the deleter type D for theunique_ptr<T,D>
it returns which would contain an allocator object and invoke both destroy and deallocate in its operator().
On the other hand, the following code works (even it's not what you expect).
// the 1st template parameter is specified as AVFrame
// the 2nd template parameter is deduced as {AVFrame*}
// construct a std::unique_ptr<AVFrame, std::default_delete<AVFrame>>
std::make_unique<AVFrame>(av_frame_alloc());
Upvotes: 2