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.