I'm trying to create a header-only C++ library around an external C API.
The C API uses void *
pointers as handles.
Here's the idea:
// resource.hpp
class Resource {
public:
// RAII constructor, destructor, etc.
// ...
void do_something(const Handle & h) {
do_something_impl( (void *) h);
}
};
// handle.hpp
class Handle
{
public:
Handle(size_t n, const Resource & res)
: p_(res.allocate(n)), res_(res) {}
// cast operation
operator void *() const { return p_; }
private:
void * p_;
Resource & res_;
};
The problem here is that (a) the Handle has to keep a reference to the Resource, and (b) the Resource needs to be able to cast the Handle to a void *. Unfortunately this leads to a circular dependency.
Any ideas on how to restructure this?
NOTE: The answer is not to simply "include xxx.hpp" or forward declare one of the classes. This needs to be restructured somehow, I just can't quite see how.
Adding a class Handle
as a forward declaration to the top of the Resource file doesn't work, because the (void *)
cast is part of the Handle definition that Resource still can't see. Likewise, changing the cast to a void * ptr()
member function leads to the same problem.
Moving the function definitions to a .cpp file is also not an answer -- it needs to be header-only.
Well, it's templates to the rescue (AGAIN!):
// resource.hpp
class Resource;
template<typename TResource> class Handle;
class Resource {
public:
// RAII constructor, destructor, etc.
// ...
void do_something(const Handle<Resource> & h) {
do_something_impl( (void *) h);
}
};
// handle.hpp
template<class TResource>
class Handle {
public:
Handle(size_t n, const TResource & res)
: p_(res.allocate(n)), res_(res) {}
// cast operation
operator void *() const { return p_; }
private:
void * p_;
TResource & res_;
};