Best way to use RAII conditionally

I have a good resource management class. For concreteness, let it be the File class for managing the file * (handling opening and closing operations)

What is the usual approach when there are cases when the resource does not need to be managed by me, and someone else is responsible?

For illustrative purposes, I currently have something like this:

int main(int argc, char** argv)
{
    File my_file(argv[1]); //I unconditionaly obtain the resource
    //...
    return 0;  //and unconditionally relinquish with the destructor
}

And I want something like

int main()
{
    if(argc <= 1){
        //use stdin that is already available
    }else{
        //obtain a file from argv[1]
    }
    //...
    if(argc <= 1){
        //nothing to do
    }else{
        //close the file we obtained
    }
}

(but less ugly, more reliable, etc.)

+3
source share
4 answers

RAII , , . , , , , , .

, , . , . Attach, . .

+2

boost::shared_ptr . , , no-op:

namespace {
template<typename T>
void noop_destruct(T *) throw() { }
}

template<typename T>
boost::shared_ptr<T> make_dummy_shared_ptr(T *p) {
    return boost::shared_ptr<T>(p, noop_destruct);
}

, RAII, boost::shared_ptr, , - , .

+6

You can use the logic of whether to use a resource inside your resource management class. Then this is no longer arbitrary. Just do

int main(int argc, char** argv)
{
    File my_file(argc > 1 ? argv[1]: NULL); //If NULL, File will point to stdin
    //...
    return 0;  //File destructor will run, relinquishing resources if necessary.
}
+2
source

Most common patterns do not allow this. However, you can enable custom distribution plugins for which the Standard has containers for it that will allow the use of these semantics. This is a short sample -

class Allocator {
    File* Allocate(...) {
        return fopen(...);
    }
};
class MyStdinAllocator {
    File* Allocate(...) {
        return ...;
    }
};
template<typename MyAllocator = Allocator> class File {
    File* ptr;
    Allocator alloc;
    File(..., const Allocator& allocref)
    : alloc(allocref) {
        ptr = alloc.Allocate(...);
    }
};
0
source

All Articles