Re: Do exception classes still need no-fail copy constructors, in C++0x?
When writing a custom exception class in C++03, it's recommended to have
its copy constructor supporting the no-fail guarantee, to prevent the
exception handling mechanism from calling std::terminate(). [...]
I got the impression that in C++0x, it's good enough to just make
sure that the exception class has a non-failing move constructor.
Howard Hinnant replied:
#include <iostream>
class A
{
A(const A&);
A& operator=(const A&);
public:
A() {}
A(A&&) {}
};
void f()
{
A a;
throw a;
}
int main()
{
try
{
f();
}
catch (A&)
{
std::cout << "Pass\n";
}
}
Outputs "Pass". Furthermore it doesn't compile if the move constructor
is commented out.
Thank you, Howard! Interestingly, your program *does* compile on the
compiler I'm currently using, when the move constructor commented out.
It only gets me an error at link time:
error LNK2019: unresolved external symbol "private: __thiscall
A::A(class A const &)" (??0A@@AAE@ABV0@@Z) referenced in function "void
__cdecl f(void)" (?f@@YAXXZ)
This link error would be easily fixed, just by implementing the copy
construction, while keeping it private! Is that according to the
Standard?
Certainly if you catch by value, instead of by
reference, you'll need a copy ctor.
Ok, but that wouldn't be a reason for me to care too much about making
the copy constructor non-throwing. The end user can easily
try-and-catch a bad_alloc caused by a catch by value. It's the
std::terminate() scenario's that scare me!
BTW, catch by value isn't recommended anyway. (Scott Meyers, More
Effective C++, Item 13: Catch exceptions by reference.) So I might even
prefer the end user to get a compile-time error, when she catches an
instance of my exception class by value...
Also if you use the (brand new, N2179):
std::exception_ptr e = std::current_exception();
You may need a copy constructor as well. And making your exception
types usable with std::current_exception() is probably motivation enough
to keep them copyable
Thanks! But does the copy constructor of my exception class need to be
non-throwing, in order to avoid an std::terminate()? At least it seems
like std::current_exception() won't terminate when my exception class
throws a bad_alloc:
exception_ptr current_exception();
Returns: An exception_ptr that refers to the currently handled exception
or a copy of the currently handled exception, or a null exception_ptr if
no exception is being handled. If the function needs to allocate memory
and the attempt fails, it returns an exception_ptr that refers to an
instance of bad_alloc.
( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html )
Also I'm wondering, do I need to provide std::current_exception() a
*public* copy constructor?
(non-mutable refcounted strings are still a valuable tool :-)).
For the exception class I wrote, I manually reference-counted the
collection of std::strings that it contained... which was quite a pain!
Kind regards,
Niels
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]