Search code examples
c++raii

Is it possible to do RAII without exceptions?


If the resource one requires to acquire in the construction of an object can fail is it possible to do RAII, if exceptions are prohibited by a local coding standard?

If so, what is the canonical manner to handle the failure of resource acquisition in this case?


Solution

  • I would not go with the invalid object approach in general because I would consider this as bad design. After construction, the object must be in a state where the invariants are established (that is the only purpose a constructor should serve). Consider a class strange_vector implementing something like std::vector, but after calling strange_vector<int>(10, 0), the object would be in an unusable state because the allocation failed.

    Instead I would declare the constructors private and use a factory method which returns an optional:

    class file
    {
    public:
        ~file() {fclose(m_file);}
    
        static std::optional<file> open(std::string const& filename)
        {
            auto f = fopen(filename.c_str(), "r");
            if (f)
            {
                return std::make_optional<file>(f);
            }
            else
            {
                return std::nullopt;
            }
        }
    
    private:
        file(FILE* file);
        FILE* m_file;
    };
    

    One of the biggest benefits of exception handling is (besides decoupling error handling and normal code path) that you cannot ignore them accidentally. If you want that, you could create your own class similar to optional that, when not initialized with a valid object, logs an error message and terminates your program (or any other reasonable error handling). I think there is a talk from A. Alexandrescu about systematic error handling where he implements a class Expected<T> that contains either a value of type T or an exception. You could use this a basis and instead of the exception add your error handling there.

    std::optional is not part of the standard yet, but you can easily get implementations either as part of recent compilers, in boost, or in other libraries.