I have a function that operates on a big chunk of data passed in as a sink argument. My BigData
type is already C++11-aware and comes with fully functional move constructor and move assignment implementations, so I can get away without having to copy the damn thing:
Result processBigData(BigData);
[...]
BigData b = retrieveData();
Result r = processBigData(std::move(b));
This all works perfectly fine. However, my processing function may fail occasionally at runtime resulting in an exception. This is not really a problem, since I can just fix stuff and retry:
BigData b = retrieveData();
Result r;
try {
r = processBigData(std::move(b));
} catch(std::runtime_error&) {
r = fixEnvironmnentAndTryAgain(b);
// wait, something isn't right here...
}
Of course, this won't work.
Since I moved my data into the processing function, by the time I arrive in the exception handler, b
will not be usable anymore.
This threatens to drastically reduce my enthusiasm for passing sink arguments by-value.
So here is the question: How to deal with a situation like this in modern C++ code? How to retrieve access to data that was previously moved into a function that failed to execute?
You may change the implementation and interfaces for both BigData
and processBigData
as you please. The final solution however should try to minimize drawbacks over the original code regarding efficiency and usability.
Result
is just calculated fromb
, it does not contain a reference to, or copy of the originalb
. – Redb
is discarded by the processing function as soon as it returns. – Redconst&
would require me to copy the whole data (I actually ran into this problem in an asynchronous processing function, so ownership of the data really needs to be moved to the function). The best solution I could think of to avoid a copy is to use a shared_ptr and go through the heap, but I'd like to avoid that if possible. – RedResult processBigData(BigData&& in_ref, BigData* out_ref=NULL){BigData whereitmoves(std::foreward(in_ref));try{/*old method*/}catch(...){if (out_ref){*out_ref=std::move(whereitmoves);} std::rethrow_exception(std::current_exception());}
– Flagellant