First of all, there is a (widespread) confusion, so let me clear it.
RAII stands for Resources Acquisition Is Initialization. The concern here is one of class invariants, and tying the acquisition of the resource to the construction of the object means that: whenever you have an handle on such an object, it is backed by a resource.
Or put another way, if acquiring the resource fail, then the object is never born (its constructor aborts/throws/whatever).
However, because typically RAII containers will also take care of releasing the resource upon their destruction, RAII is often colloquially used to refer to proper resource management. This is beyond its scope though, and a container such as:
struct RaiiHandle {
RaiiHandle(Handle& h): handle(h) {}
Handle& handle;
};
which does nothing about resource management is still a RAII container as it guarantees the presence of the resource.
Other acronyms have been tried to express the proper management of resources, such as SBRM: Scope Bound Resource Management, however they did not take (in SBRM case, it fails to account for the fact that a resource is not necessarily tied to a lexical scope).
A word of caution on your interface.
In the days of C, there was a piece of wisdom that said that whoever allocated a resource (often memory) should also provide a method to deallocate it. This ensured that the resource was properly deallocated because only its creator knows how it was allocated. Even today, it still remains a good advice.
Your interface, however, suffers from asymmetry: you are passed a pointer and call delete
on it. But what if it was a pointer to an array ? What if it was a stack object ? Calling delete
is preposterous.
A word of caution on your implementation.
I hope for your sake this is a trimmed down example, however since they are missing I cannot help but remind you that you should follow the Rule of Three (make it Five in C++11).
A very simple way never to forget is to change your raw pointer for a unique_ptr
(possibly with a custom deleter). It will have correct move members by default and will force you to write the copy members should you need them.
Back to your question: Yes in general you will need a way to access the underlying resource, otherwise it would be useless.
There are multiple ways though:
- if your container is specialized, it may present a domain oriented interface, this is what
fstream
does for example: you do not access the FILE*
or whatever is inside, but instead use <<
and >>
and .eof()
, etc..
- you may return a handle (pointer or reference)
- you may have a method that takes a functor and will call it with a reference to the object (more functional oriented, less seen in C++)
It is up to you to design the interface so that your clients may actually use the resource.