Default constructors for Series and SeriesIterator#955
Conversation
5e0ba01 to
99e7467
Compare
| * @return true If a Series has been opened for reading and/or writing. | ||
| * @return false If the object has been default-constructed. | ||
| */ | ||
| operator bool() const; |
There was a problem hiding this comment.
Uff, but don't we have to check this one now at the beginning of every public Series method call?
Otherwise we can have an invalid Series object, don't we?
There was a problem hiding this comment.
We could theoretically do this check within Series::get and it would then happen automatically at every public Series method call. But I don't know if we should.
Basically, #886 applied shared_ptr semantics to our Series class and this PR just follows this one step further: You can default-construct a Series / a shared_ptr, but then it will be empty. You can construct a Series / a shared_ptr with content and only then can you use it. So, maybe we can add this to the documentation of Series that it strives to work like a shared_ptr on some internally-held resources?
Btw, reason for this change: In GAPD, there is a struct that holds all of the necessary data for doing IO. Adding the Series and the Series iterators to that struct means it is not default-constructible any more which is rather annoying to use.
There was a problem hiding this comment.
Thanks for the details.
My thinking is along the lines what we want to do with a default-constructed Series. Can we still open a proper data series with it later on? And what happens if someone uses it accidentally as if it was already holding a valid data series, would it give a clear error message?
There was a problem hiding this comment.
Can we still open a proper data series with it later on?
Yep, by using operator=(),e.g.:
Series series;
if( use_hdf5 ) {
series = Series( "data.h5", Access::CREATE );
}
else {
series = Series( "data.bp", Access::CREATE );
}And what happens if someone uses it accidentally as if it was already holding a valid data series, would it give a clear error message?
What would happen would currently depend on your STL implementation of shared_ptr, but it would be exactly what would happen upon dereference of an empty shared_ptr.
So both points mimic exactly the behavior of shared pointers.
There was a problem hiding this comment.
What would happen would currently depend on your STL implementation of shared_ptr, but it would be exactly what would happen upon dereference of an empty shared_ptr.
Hm, I fear that is undefined behavior and we should guard the user from it with an exception instead, what do you think? https://en.cppreference.com/w/cpp/memory/shared_ptr
There was a problem hiding this comment.
Discussed offline: let's implement the check in Series::get and throw a clean exception if the Series is still default-constructed / owning a nullptr
99e7467 to
3e67617
Compare
I've noticed that those can be useful in user code. E.g. in GAPD, openPMD is only one of the many reading routines, making it impossible to use our
for(auto iteration: series.readIterations())…API, instead resorting to manually using the iterators. That is easier if the iterators are default-constructible.