Reputation: 3871
I'm trying to pop_back my shared_pointer from my vector and convert to a unique_ptr. Unfortunately, it's giving a strange compilation message.
IFCCB.cpp:
std::unique_ptr<IFC> IFCCCB::getElementVectorIFC()
{
return (std::unique_ptr<IFC>(make_unique<IFC>(m_shpVectorIFC.pop_back())));
}
IFCCB.h:
public:
unique_ptr<IFC> getElementVectorIFC();
compile error:
error C2784: 'enable_if::value,std::unique_ptr<_Ty,std::default_delete<_Ty>>>::type std::make_unique(_Types &&...)' : could not deduce template argument for '_Types &&' from 'void'
As far as I can tell, I'm doing what I see elsewhere.
I looked at make_unique info but it doesn't give a very good example, and unique_ptr use. Any ideas?
Upvotes: 1
Views: 2544
Reputation: 275260
There are many things wrong here:
return (std::unique_ptr<IFC>(make_unique<IFC>(m_shpVectorIFC.pop_back())));
Let us break it down into multiple lines, C++11 style. This isn't quite equivalent, but close:
auto&& a = m_shpVectorIFC.pop_back();
auto&& b = make_unique<IFC>(std::move(a));
auto&& c = std::unique_ptr<IFC>(std::move(b));
return std::move(c);
which isn't a bad technique to start with.
Now you'll get an error that will be more informative.
The first problem is that pop_back()
returns void
. Fix that with:
auto a = std::move(m_shpVectorIFC.back()); // note a value, as we are about to mutate the vector
m_shpVectorIFC.pop_back();
auto&& b = make_unique<IFC>(std::move(a));
auto&& c = std::unique_ptr<IFC>(std::move(b));
return std::move(c);
we still run into problems. IFC
cannot be constructed from a std::shared_ptr<IFC>&&
. It cannot. We can make a copy:
auto a = std::move(m_shpVectorIFC.back());
m_shpVectorIFC.pop_back();
auto&& b = make_unique<IFC>(*a);
auto&& c = std::unique_ptr<IFC>(std::move(b));
return std::move(c);
Next, auto&&c
is pointless.
auto a = std::move(m_shpVectorIFC.back());
m_shpVectorIFC.pop_back();
auto&& b = make_unique<IFC>(*a);
return std::move(b);
and we might as well store b
as a value:
auto a = std::move(m_shpVectorIFC.back());
m_shpVectorIFC.pop_back();
auto b = make_unique<IFC>(*a);
return b;
then some error detecting:
auto a = std::move(m_shpVectorIFC.back());
m_shpVectorIFC.pop_back();
if (!a)
return {};
auto b = make_unique<IFC>(*a);
return b;
and micro-optimize:
auto a = std::move(m_shpVectorIFC.back());
m_shpVectorIFC.pop_back();
if (!a)
return {};
auto b = a.unique()?make_unique<IFC>(std::move(*a)):make_unique<IFC>(*a);
return b;
Now, this doesn't return the shared_ptr
data, but rather a copy of it. You cannot move the guts of a C++11 shared_ptr
into a unique_ptr
. You can do it the other way.
Odds are you should be storing a unique_ptr
in your vector anyhow.
Upvotes: 4
Reputation: 3022
std::vector::pop_back
returns void
. That's the reason you are getting that specific error, however once you fix that then you will encounter the problem the others mention.
Upvotes: 3
Reputation: 69854
i should think something like this would be preferable (assuming m_shpVectorIFC contains unique_ptr objects):
std::unique_ptr<IFC> IFCCCB::getElementVectorIFC()
{
auto result = std::move(m_shpVectorIFC.back());
m_shpVectorIFC.pop_back();
return result;
}
EDIT: ah, just seen the word shared_ptr in there... nope, you have to return a shared_ptr or store a unique_ptr in the container.
Upvotes: 1
Reputation: 254431
You can't transfer ownership from a shared pointer to a unique pointer. Once ownership is shared, it remains shared.
Either store unique pointers if you don't need to share ownership with the container, or continue to use shared pointers after removing from the container if you do.
Upvotes: 5