Reputation:
I've these plain C functions from a library:
struct SAlloc;
SAlloc *new_salloc();
void free_salloc(SAlloc *s);
Is there any way I can wrap this in C++ to a smart pointer (std::unique_ptr), or otherwise a RAII wrapper ?
I'm mainly curious about the possibilities of the standard library without creating my own wrapper/class.
Upvotes: 7
Views: 2085
Reputation: 275650
Another variation:
#include <memory>
struct SAlloc {
int x;
};
SAlloc *new_salloc() { return new SAlloc(); }
void free_salloc(SAlloc *s) { delete s; }
struct salloc_freer {
void operator()(SAlloc* s) const { free_salloc(s); }
};
typedef std::unique_ptr<SAlloc, salloc_freer> unique_salloc;
template<typename... Args>
unique_salloc make_salloc(Args&&... args) {
auto retval = unique_salloc( new_salloc() );
if(retval) {
*retval = SAlloc{std::forward<Args>(args)...};
}
return retval;
}
int main() {
unique_salloc u = make_salloc(7);
}
I included a body to SAlloc
and the various functions to make it a http://sscce.org/ -- the implementation of those doesn't matter.
So long as you can see the members of SAlloc
, the above will let you construct them like in an initializer list at the same time as you make the SAlloc
, and if you don't pass in any arguments it will zero the entire SAlloc
struct
.
Upvotes: 0
Reputation: 27365
Is there any way I can wrap this in C++ to a smart pointer (
std::unique_ptr
), or otherwise a RAII wrapper ?
Yes. You need here a factory function, that creates objects initializing the smart pointer correctly (and ensures you always construct pointer instances correctly):
std::shared_ptr<SAlloc> make_shared_salloc()
{
return std::shared_ptr<SAlloc>(new_salloc(), free_salloc);
}
// Note: this doesn't work (see comment from @R.MartinhoFernandes below)
std::unique_ptr<SAlloc> make_unique_salloc()
{
return std::unique_ptr<SAlloc>(new_salloc(), free_salloc);
}
You can assign the result of calling these functions to other smart pointers (as needed) and the pointers will be deleted correctly.
Edit:
Alternately, you could particularize std::make_shared
for your SAlloc.
Edit 2:
The second function (make_unique_salloc
) doesn't compile. An alternative deleter functor needs to be implemented to support the implementation.
Upvotes: 0
Reputation: 26546
I like R. Martinho Fernandes' answer, but here's a shorter (but less efficient) alternative:
auto my_alloc = std::shared_ptr<SAlloc>(new_salloc(), free_salloc);
Upvotes: 3
Reputation: 234524
Yes, you can reuse unique_ptr for this. Just make a custom deleter.
struct salloc_deleter {
void operator()(SAlloc* s) const {
free_salloc(s); // what the heck is the return value for?
}
}
using salloc_ptr = std::unique_ptr<SAlloc, salloc_deleter>;
Upvotes: 14