Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I have an auto_ptr in an Exception class

I have a problem with auto_ptr in Exception classes, that I eventually reduced to:

#include <memory>

class MyException
{
    std::auto_ptr<int> m_foo2;
};

int main()
{
    try
    {
        throw MyException();
    }
    catch (const MyException&)
    {

    }
    return 0;
}

This fails to compile with:

/perforce/unstable/test/Common/Exceptions/TestException4.cpp: In function 'int main()': /perforce/unstable/test/Common/Exceptions/TestException4.cpp:12: error: no matching function for call to 'MyException::MyException(MyException)' /perforce/unstable/test/Common/Exceptions/TestException4.cpp:4: note: candidates are: MyException::MyException() /perforce/unstable/test/Common/Exceptions/TestException4.cpp:4: note: MyException::MyException(MyException&) /perforce/unstable/test/Common/Exceptions/TestException4.cpp:12: error: in thrown expression

And the error goes away if I remove the auto_ptr.

Is this because the exception is being copied or assigned? Is there a way of using auto_ptrs in an Exception?

like image 302
Douglas Leeder Avatar asked Apr 05 '12 10:04

Douglas Leeder


1 Answers

Is this because the exception is being copied or assigned?

Indeed it is. The standard specifies how an exception is thrown in C++11 15.1/3:

A throw-expression initializes a temporary object, [...]. The temporary is an lvalue and is used to initialize the variable named in the matching handler.

The initialisation is done with the implicit copy constructor. This is declared as MyException(MyException&), since there is a member that requires a non-const reference argument (as specified in C++11 12.8/9). The temporary object can't be bound to a non-const reference, and so the construction fails.

Is there a way of using auto_ptrs in an Exception?

If you're able to use C++11, then you could use unique_ptr instead, and consign auto_ptr to the bowels of history. Your class would have an implicit move constructor, declared as MyException(MyException&&), which could be used to initialise it from a temporary.

Otherwise, you could throw a non-temporary value:

MyException ex;
throw ex;

or you could hack your class to allow initialisation from a const reference by adding an explicit copy constructor and using const_cast or mutable to allow that to copy the auto_ptr - but that is potentially dangerous, and I wouldn't recommend it.

like image 97
Mike Seymour Avatar answered Sep 22 '22 07:09

Mike Seymour