Re: Do exception classes still need no-fail copy constructors, in C++0x?
In article <46A702C9.42ED208A@this.is.invalid>,
noreply@this.is.invalid (Niels Dekker - no return address) wrote:
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?
I believe C++03 requires "a" to be copied, and for that matching
constructor to be accessible. It also allows that copy to be elided.
But whether or not the copy is elided, the constructor must be
accessible.
C++0X will change those rules only by treating "a" as an rvalue when
searching for a constructor to make the copy. If that fails to find a
match, a second pass is made treating "a" as an lvalue. Whatever is
matched, is then checked for accessibility. And if an accessible
(matching) constructor is found, it is then permitted to be elided.
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:
I believe that N2179 specifies that if your exception copy ctor throws,
exception_ptr will simply be set to bad_alloc (please correct me if I'm
wrong Peter). terminate() will not be called.
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?
Morally yes, but I'm not positive that such a requirement can be
enforced. Some implementations probably won't even attempt a copy of
the exception under current_exception() (and some will). If a copy is
attempted, I'm not sure what the behavior will be if it is not
accessible.
-Howard
---
[ 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 ]