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?
Indeed it is. The standard specifies how an exception is thrown in C++11 15.1/3:
The initialisation is done with the implicit copy constructor. This is declared as
MyException(MyException&), since there is a member that requires a non-constreference argument (as specified in C++11 12.8/9). The temporary object can’t be bound to a non-constreference, and so the construction fails.If you’re able to use C++11, then you could use
unique_ptrinstead, and consignauto_ptrto the bowels of history. Your class would have an implicit move constructor, declared asMyException(MyException&&), which could be used to initialise it from a temporary.Otherwise, you could throw a non-temporary value:
or you could hack your class to allow initialisation from a
constreference by adding an explicit copy constructor and usingconst_castormutableto allow that to copy theauto_ptr– but that is potentially dangerous, and I wouldn’t recommend it.