New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DM-9932: Make afw classes RFC-209 compliant #312
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
I've made a number of small suggestions, mostly on ways in which you could go a bit further to clean things up a bit more. Feel free to ignore anything you think is out of scope, especially the areas where I'm advocating something that's not as precisely backwards-compatible as everything else you've done.
AffineTransform(AffineTransform const &) = default; | ||
AffineTransform(AffineTransform &&) = default; | ||
~AffineTransform() = default; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think assignment can be defaulted for this class, too; the implementation later in the class declaration should be equivalent to that.
include/lsst/afw/geom/Box.h
Outdated
@@ -101,6 +101,9 @@ class Box2I { | |||
|
|||
/// Standard copy constructor. | |||
Box2I(Box2I const& other) : _minimum(other._minimum), _dimensions(other._dimensions) {} | |||
// Delegate to copy-constructor for backwards-compatibility | |||
Box2I(Box2I&& other) : Box2I(other) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm quite confident that defaults are fine for all compiler-generated member functions in this class.
I also understand if you'd prefer to just adhere strictly to your current guidelines, but I'll keep noting the ones I'm certain about as I go.
include/lsst/afw/geom/Box.h
Outdated
// Delegate to copy-constructor for backwards compatibility. | ||
Box2D(Box2D&& other) : Box2D(other) {} | ||
|
||
~Box2D() = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Defaults for all compiler-generated functions would be fine for Box2D
.
CoordinateBase(CoordinateBase&&) = default; | ||
CoordinateBase& operator=(CoordinateBase const&) = default; | ||
CoordinateBase& operator=(CoordinateBase&&) = default; | ||
virtual ~CoordinateBase() = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CoordinateBase
's destructor should not be virtual
; it's a CRTP base class, and we never hold its subclasses by a base class reference or pointer.
Note that virtual
needs to be removed from the other specializations in this file as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems like a strange thing to guarantee. Why bother using inheritance, then? Keeping it virtual
seems safer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I misspoke; we never delete its subclasses via a base class reference or pointer, which is much easier to guarantee. In this case, we also very rarely use the classes via a base class reference or pointer, but that's not an essential part of the pattern. For example, Eigen uses CRTP extensively, and the templated base classes are very much a part of the interface. It also doesn't define its destructors as virtual, because the base classes are by definition only used in contexts in which you can safely static_cast
them a more derived class that can be inferred from their template arguments.
It's probably best to just say that because CRTP is essentially compile-time polymorphism, many of the usual rules of C++ inheritance that are derived from runtime polymorphism don't apply. I think a good case could be made that the implementations of Point
and Extent
don't actually benefit from these base classes much (they add a lot of boilerplate in exchange for reducing a bit of other code duplication), and I'd probably be supportive of a ticket to remove them, but we should absolutely not add a vtable to any of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no idea what you mean by "rules of C++ inheritance"; the principles of inheritance are language-independent. But it is true that none of the classes in question contain other virtual
methods, so they can't really be used as interfaces anyway. I'll change the declarations.
include/lsst/afw/geom/Extent.h
Outdated
ExtentBase(ExtentBase &&) = default; | ||
ExtentBase &operator=(ExtentBase const &) = default; | ||
ExtentBase &operator=(ExtentBase &&) = default; | ||
virtual ~ExtentBase() = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should not be virtual
(same reasons as CoordinateBase
). Also other specializations in this file.
src/formatters/MaskFormatter.cc
Outdated
@@ -84,7 +84,7 @@ MaskFormatter<MaskPixelT>::MaskFormatter(std::shared_ptr<lsst::pex::policy::Poli | |||
: lsst::daf::persistence::Formatter(typeid(this)) {} | |||
|
|||
template <typename MaskPixelT> | |||
MaskFormatter<MaskPixelT>::~MaskFormatter(void) {} | |||
MaskFormatter<MaskPixelT>::~MaskFormatter(void) = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Archaic void
.
@@ -110,7 +110,7 @@ MaskedImageFormatter<ImagePixelT, MaskPixelT, VariancePixelT>::MaskedImageFormat | |||
: lsst::daf::persistence::Formatter(typeid(this)) {} | |||
|
|||
template <typename ImagePixelT, typename MaskPixelT, typename VariancePixelT> | |||
MaskedImageFormatter<ImagePixelT, MaskPixelT, VariancePixelT>::~MaskedImageFormatter(void) {} | |||
MaskedImageFormatter<ImagePixelT, MaskPixelT, VariancePixelT>::~MaskedImageFormatter(void) = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Archaic void
.
src/formatters/TanWcsFormatter.cc
Outdated
TanWcsFormatter& TanWcsFormatter::operator=(TanWcsFormatter const&) = default; | ||
TanWcsFormatter& TanWcsFormatter::operator=(TanWcsFormatter&&) = default; | ||
|
||
TanWcsFormatter::~TanWcsFormatter(void) = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Archaic void
.
src/formatters/WcsFormatter.cc
Outdated
WcsFormatter& WcsFormatter::operator=(WcsFormatter const&) = default; | ||
WcsFormatter& WcsFormatter::operator=(WcsFormatter&&) = default; | ||
|
||
WcsFormatter::~WcsFormatter(void) = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Archaic void
.
src/geom/Point.cc
Outdated
for (int n = 0; n < N; ++n) { | ||
this->_vector[n] = other[n]; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be able to default this instead (same later in this file); I can confirm that that would be equivalent for this class.
a71567b
to
83cc12c
Compare
83cc12c
to
24a8078
Compare
This PR changes all classes to have explicitly declared compiler-generated members, as adopted in RFC-209. I tried to make changes according to the following principles:
default
keyword.