I have a variable which accumulates the current exception and needs to get cleaned when the current exception gets thrown (so that the same error does not get reported again). The problem is that throw std::move(ex);
does not call the move constructor (which would clean ex
), but rather calls a copy constructor (so that ex
stays with the already thrown errors too). A MVCE follows:
#include <iostream>
#include <stdexcept>
#include <string>
using namespace std;
class ThrowMoveTest : exception
{
public:
ThrowMoveTest(const string& what)
{
_what = what;
}
ThrowMoveTest(const ThrowMoveTest& fellow)
{
cout << "Copy " << what() << endl;
_what = fellow._what;
}
ThrowMoveTest(ThrowMoveTest&& fellow)
{
cout << "Move " << what() << endl;
_what = std::move(fellow._what);
}
virtual const char* what() const override
{
return _what.c_str();
}
private:
mutable string _what;
};
int main()
{
try
{
ThrowMoveTest tmt1("Test1");
throw move(tmt1);
}
catch (const ThrowMoveTest& ex)
{
cout << "Caught " << ex.what() << endl;
}
return 0;
}
I am using MSVC++2013 Update 5.
Is there something that I am doing wrong so that the move constructor does not get called for this reason? Is there away to throw an exception so that the temporary object used for exception storage in C++ gets move-constructed, rather than copy-constructed from the original?
What I try to avoid is double-copying: construction of a copy of tmt1
, then cleaning the original, then using the copy in throw
statement, which would construct another copy for temporary storage.
EDIT: The above code example gives the following output on MSVC++2013 Update 5
Copy
Caught Test1
While the expected output is
Move
Caught Test1
EDIT2: Submitted a compiler bug report https://connect.microsoft.com/VisualStudio/feedback/details/1829824