Reputation: 197
How can I pass smart ptr to a function taking reference to a pointer as a parameter?
smart_ptr<T> val; // I have this smart pointer
// And I want to pass it to this function, so that this function will fill the smart pointer with proper value
void Foo(T*& sth)
{
sth = memoryAddress;
}
EDIT Now I get it. Thanks guys for all the answers!
Upvotes: 4
Views: 1786
Reputation: 234654
Ugh, this API is ugly.
I will assume that the function promises the pointer it "returns" owns a resource that is to be deleted by the caller in the way that smart_ptr
does so, and that the smart_ptr
can be initialised from an arbitrary pointer. It cannot be done otherwise.
You can just grab the pointer as you would in the absence of smart pointers and then put it in the smart pointer.
T* ptr;
Foo(ptr);
smart_ptr<T> val(ptr);
It may be the case that the smart pointer already owns something and you want to pass that something to the function, and then replace what the smart pointer owns. That's... even uglier.
I don't know if the function will take ownership of the resource you pass in (normally, I would expect not, but since the API is this ugly, I am not going to swear by it). That leads to two different scenarios.
If the function takes ownership of the resource you pass, i.e., it cares about deleting the pointer itself, the smart pointer type must be one that can relinquish ownership of the resource, like std::unique_ptr
with the release()
member function. Notably, std::shared_ptr
cannot do this (consider that other shared_ptr
s may also own it).
So, assuming that the smart pointer has that capability, and the ability to be reinitialised to an arbitrary pointer (like with std::unique_ptr::reset
) you can do as follows:
//smart_ptr<T> val;
T* ptr = val.release();
Foo(ptr);
val.reset(ptr);
If the function does not take ownership of the resource, all that is required is the ability to reinitialise with an arbitrary pointer.
//smart_ptr<T> val;
T* ptr = val.get();
Foo(ptr);
val.reset(ptr);
Upvotes: 4
Reputation: 26576
You can't do that. You can pass the raw pointer using "T* raw = val.get()
" then "Foo(raw)
" but you can't set a shared_ptr
's raw pointer like that inside Foo
. If you want Foo
to set the shared_ptr
, make it take a non-const shared_ptr
reference.
Like this:
template<typename T>
Foo(shared_ptr<T>& ptr)
{
ptr.reset(memoryAddress); // Or assign it, or make_shared, or whatever.
}
shared_ptr<int> intptr;
Foo(intptr);
Or better yet, make Foo
return a shared_ptr
rather than take it by reference.
Upvotes: 1
Reputation: 154047
The simple answer is that you can't. While the smart pointer
almost certainly contains a T*
somewhere internally, smart
pointers enforce all sorts of invariants, many of which could be
broken if you could change this pointer without passing through
the user interface. The only solution is to call the function
with a raw pointer, and then use the raw pointer to initialize
the smart pointer, provided that you're sure that the pointer
you get meets the requirements of the smart pointer (e.g.
allocated by the new
operator).
Upvotes: 7