Reputation: 16677
I have something like:
#include "MyImage.hpp" // MyImage wraps the Qt library image class
namespace fs = boost::filesystem;
class ImageCollection {
public:
ImageCollection(const char* path);
private:
const fs::path path_;
deque<MyImage> instanceDeque_;
}
ImageCollection(const char* path) :
path_(fs::is_directory(path) ?
fs::complete(path) :
fs::complete(path).parent_path()) /* Can I even do this? */
{
/*** code in question ***/
fs::directory_iterator endIter;
for(fs::directory_iterator dirIter(path_); dirIter != endIter; dirIter++) {
instanceDeque_.push_back(MyImage(*dirIter));
}
}
The MyImage constructor throws a MyInvalidFileException when *dirIter is a fs::path to a non-image file.
I'd like MyImage and ImageCollection to be immutable.
Can I:
try {
instanceDeque_.push_back(MyImage(*dirIter));
}
catch(const MyInvalidFileException& e) { // oops, tnx Nemanja T.
// remember *dirIter in a list of non-Image files, to use later
continue;
}
What happens when it throws? Is there a zombie MyImage or a zombie element left in the deque? Or is this actually the right way to do it? (i.e. the push_back() is aborted and no MyImage is created.)
I currently have a messy workaround:
// load up an empty MyImage, which I'd rather not do
instanceDeque_.push_back(MyImage());
for(fs::directory_iterator dirIter(path_); dirIter != endIter; dirIter++) {
MyImage& attemptImage = instanceDeque_.back();
bool success = attemptImage.loadPath(*dirIter); // "fill" the empty MyImage
if (success)
instanceDeque_.push_back(MyImage()); // prepare another empty MyImage
}
instanceDeque_.pop_back(); // discard the empty MyImage
Where MyImage is initialized with a null QImage*, and loadPath() creates a QImage on the heap. This forces me to have null pointer checks everywhere. I figure there should be a way to have an instance of QImage if the file can be opened, and the construction to just fail if the file can't.
Upvotes: 2
Views: 142
Reputation: 7921
As others have already mention, if the MyImage
constructor throws then you'll never reach the deque.push_back
function so that will not be a problem. Also if it does make it into the push_back
function and it throws for some reason, then your deque object will remain unchanged. The STL does not allow methods to modify/corrupt the container if the operation fails. I couldn't find anything about push_back
throwing in the documentation, so you probably don't have to worry about that unless you run out of memory or some other extreme case.
Upvotes: 1
Reputation: 52519
If MyImage(*dirIter)
fails you will not get into push_back
so that's not a problem.
Upvotes: 1
Reputation: 22149
It depends on MyImage
I guess. If there is an exception in the constructor of MyImage it should fail before you even reach the push_back
method. This is because the constructor will be run before the push_back
(which is logical, since it needs a value to pass the method). Thus if that step fails and exception is thrown, push_back
will never be reached.
Here are some pointers:
Upvotes: 2