I am using the library igraph and the library uses a lot of allocating and freeing memory using custom functions. I want to remove the possibility of forgetting to free memory by using RAII.
The code beforehand looks something like this:
void doSomething() {
igraph_vector_t shortest_path;
igraph_get_shortest_path_dijkstra(
someargs...,
&shortest_path
someargs...
)
igraph_vector_destroy(&shortest_path);
};
I want to replace igraph_vector_t with a custom C++ class that has a destructor that calls igraph_vector_destroy so I can just do:
void doSomething() {
raii_igraph_vector_t shortest_path;
igraph_get_shortest_path_dijkstra(
someargs...,
&shortest_path
someargs...
)
}
I can make a custom class/struct like:
struct raii_igraph_vector_int {
igraph_vector_int_t vec;
~RAIIVectorInt(){
igraph_vector_int_destroy(&vec);
}
};
And I can pass it into the function like:
igraph_get_shortest_path_dijkstra(
someargs...,
&shortest_path.vec
someargs...
)
However, I was wondering if there was a way to not need to add on the .vec
and just treat it as if it were the previous type.
This should do the trick (totally untested, though):
struct DeleteIGraphVector {
void operator() (igraph_vector_t *vec) const {
igraph_vector_destroy(vec);
delete vec;
}
};
using raii_igraph_vector_t = std::unique_ptr<igraph_vector_t, DeleteIGraphVector>;
void doSomething() {
raii_igraph_vector_t shortest_path{new igraph_vector_t};
igraph_get_shortest_path_dijkstra(
someargs...,
shortest_path,
someargs...
);
}
It uses unique_ptr
with a custom deleter to destroy and then delete the igraph type appropriately. One disadvantage of this approach is that the igraph_vector_t
will be heap-allocated, though. This could be avoided with unique_resource
, which hasn't quite made it into the C++ standard yet but is available in third-party libraries.
If you don't want to write different deleters for each igraph type, you could try using templates, like this:
template<typename T, void (*f_del)(T *)>
struct GenericIGraphDeleter {
void operator() (T *obj) {
f_del(obj);
delete obj;
}
};
using raii_igraph_vector_t = std::unique_ptr<
igraph_vector_t,
GenericIGraphDeleter<igraph_vector_t, &igraph_vector_destroy>>;
using raii_igraph_vector_int_t = std::unique_ptr<
igraph_vector_int_t,
GenericIGraphDeleter<igraph_vector_int_t, &igraph_vector_int_destroy>>;