How can I wrap a C object in a custom RAII Class in C++?

Advertisements

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.

>Solution :

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.

Leave a ReplyCancel reply