Repository navigation
ENH: Select image iterator access by image constness (supersedes #7021) - #7065
hjmjohnson wants to merge 45 commits into
Conversation
# Conflicts: # Modules/Core/Common/include/itkImageRandomConstIteratorWithIndex.h # Modules/Core/Common/include/itkImageRandomConstIteratorWithIndex.hxx
This comment was marked as resolved.
This comment was marked as resolved.
614d0e2 to
6dca3f7
Compare
# Conflicts: # Modules/Core/Common/include/itkImageRandomConstIteratorWithIndex.h # Modules/Core/Common/include/itkImageRandomConstIteratorWithIndex.hxx
|
@greptileai please review the latest commits (6dca3f7). |
6dca3f7 to
1e416e2
Compare
# Conflicts: # Modules/Core/Common/include/itkImageRandomConstIteratorWithIndex.h # Modules/Core/Common/include/itkImageRandomConstIteratorWithIndex.hxx
|
@greptileai please review the latest commits (1e416e2). |
1e416e2 to
3f3d071
Compare
|
@greptileai please review the latest commits (3f3d071). |
# Conflicts: # Modules/Core/Common/include/itkImageRandomConstIteratorWithIndex.h # Modules/Core/Common/include/itkImageRandomConstIteratorWithIndex.hxx
|
Ran this PR at What was builtITK This PR and #7041 overlap in Results
* With three VNL includes added, without which elastix does not compile against ITK How each failure was tracedCompared against a build of
Outside the code this PR changes:
|
SimonRit
left a comment
There was a problem hiding this comment.
I did not do a thorough review, too many changes... But LGTM.
Thanks Simon. I just hope that others will do a thorough review, because the iterator framework is really a fundamental part of ITK. However, I also find |
Me too! It's not only the number of changes, large parts of the code have been moved without changes which makes the reviewing more difficult. The good news is that it's thoroughly tested as it is a fundamental part of ITK :-). |
git mv of each itkXxxConst* file onto the itkXxx* name; the content is unchanged. The read-only code becomes the implementation of both names, so its history follows it. This commit does not build alone.
Mechanical: in each renamed file, with C its read-only class and W the
writable one,
perl -pi -e 'next if /^\s*\*\s*\\(sa|sphinxexample)\b/;
s/\bitkC(_h|_hxx|\.h|\.hxx)\b/itkW$1/g; s/\bC\b/W/g' FILE
Other classes named in the file keep their names here.
\sa and \sphinxexample lines keep the read-only names. This commit
does not build alone.
f44a52b to
994865e
Compare
|
Force-push Checks
|
ImageReverseConstIterator offered a public Set() that cast away const, and the writable reverse iterators accepted read-only sources. ImageReverseIterator<T> and ImageRegionReverseIterator<T> now write only when T is not const, and convert only toward const; ImageReverseConstIterator<T> and ImageRegionReverseConstIterator<T> are the iterators over const T. The row spans and operator++/-- move from the region class into ImageReverseIterator, which had them through its base, so ImageReverseConstIterator gains them. The GetBufferPointer test now converts from a writable iterator.
Each XxxIterator<T> here derived from XxxConstIterator<T> and added Set() and Value() by casting away const. The next commits make the read-only class the implementation, with access selected by the constness of T, so the subclass and its out-of-line definitions go away whole; only the headers included the .hxx files. Removing the files first lets the following rename show as a pure rename. This commit does not build alone.
git mv of each itkXxxConst* file onto the itkXxx* name; the content is unchanged. The read-only code becomes the implementation of both names, so its history follows it. This commit does not build alone.
Mechanical, reproducible in the include directory with
perl -pi -e 'next if /^\s*\*\s*\\(sa|sphinxexample)\b/;
s/\bitkImageConstIteratorWithIndex(_h|_hxx|\.h|\.hxx)\b/itkImageIteratorWithIndex$1/g; s/\bImageConstIteratorWithIndex\b/ImageIteratorWithIndex/g' itkImageIteratorWithIndex.h itkImageIteratorWithIndex.hxx
\sa and \sphinxexample lines keep the read-only names. This commit
does not build alone.
Apply the ImageIterator design to the root of the WithIndex family: ImageIteratorWithIndex<T> holds the position as a pointer to const pixels only when T is const, so Set() and Value() need no const_cast and are absent for const images. ImageConstIteratorWithIndex<T> is ImageIteratorWithIndex<const T>.
Each XxxIterator<T> here derived from XxxConstIterator<T> and added Set() and Value() by casting away const. The next commits make the read-only class the implementation, with access selected by the constness of T, so the subclasses and their out-of-line definitions go away whole; only the headers included the .hxx files. Removing the files first lets the following rename show as a pure rename. This commit does not build alone.
git mv of each itkXxxConst* file onto the itkXxx* name; the content is unchanged. The read-only code becomes the implementation of both names, so its history follows it. This commit does not build alone.
Mechanical: in each renamed file, with C its read-only class and W the
writable one,
perl -pi -e 'next if /^\s*\*\s*\\(sa|sphinxexample)\b/;
s/\bitkC(_h|_hxx|\.h|\.hxx)\b/itkW$1/g; s/\bC\b/W/g' FILE
Other classes named in the file keep their names here.
\sa and \sphinxexample lines keep the read-only names. This commit
does not build alone.
Apply the ImageIteratorWithIndex design to the region, linear, slice, random, random non-repeating, and region exclusion iterators. Each XxxIteratorWithIndex<T> derives from its writable base, inherits the constness-gated Set() and Value(), and XxxConstIteratorWithIndex<T> is XxxIteratorWithIndex<const T>. The random non-repeating conversion deep-copies the permutation it owns.
Each XxxIterator<T> here derived from XxxConstIterator<T> and added Set() and Value() by casting away const. The next commits make the read-only class the implementation, with access selected by the constness of T, so the subclasses and their out-of-line definitions go away whole; only the headers included the .hxx files. Removing the files first lets the following rename show as a pure rename. This commit does not build alone.
git mv of each itkXxxConst* file onto the itkXxx* name; the content is unchanged. The read-only code becomes the implementation of both names, so its history follows it. This commit does not build alone.
Mechanical: in each renamed file, with C its read-only class and W the
writable one,
perl -pi -e 'next if /^\s*\*\s*\\(sa|sphinxexample)\b/;
s/\bitkC(_h|_hxx|\.h|\.hxx)\b/itkW$1/g; s/\bC\b/W/g' FILE
Other classes named in the file keep their names here.
\sa and \sphinxexample lines keep the read-only names. This commit
does not build alone.
The frequency-layout iterators and ReflectiveImageRegionIterator inherited from read-only bases and cast away const to write. They now derive from the writable WithIndex iterators, so writes need no cast and are unavailable for const images; each Const name is the iterator over the const image.
Each XxxIterator<T> here derived from XxxConstIterator<T> and added Set() and Value() by casting away const. The next commits make the read-only class the implementation, with access selected by the constness of T, so the subclasses and their out-of-line definitions go away whole; only the headers included the .hxx files. Removing the files first lets the following rename show as a pure rename. This commit does not build alone.
git mv of each itkXxxConst* file onto the itkXxx* name; the content is unchanged. The read-only code becomes the implementation of both names, so its history follows it. This commit does not build alone.
Mechanical: in each renamed file, with C its read-only class and W the
writable one,
perl -pi -e 'next if /^\s*\*\s*\\(sa|sphinxexample)\b/;
s/\bitkC(_h|_hxx|\.h|\.hxx)\b/itkW$1/g; s/\bC\b/W/g' FILE
Other classes named in the file keep their names here.
\sa and \sphinxexample lines keep the read-only names. This commit
does not build alone.
LineIterator and PathIterator wrote through a const_cast of the const image held by their read-only bases. Each is now the iterator, writable only when TImage is not const, and the Const name iterates over the const image. PathIterator::Value() read a nonexistent member, so it could not compile; it now returns the current pixel.
The writable flood-filled iterators cast away the const image held by ConditionalConstIterator to write a pixel. They now keep the writable image pointer their constructor receives, offer Set() only for non-const images, and read through the const image without a cast.
The hand-written copy constructors and assignment operators copied every member and reset the accessor's begin pointer to the same buffer, which the defaults also do. Copying a default-constructed ImageIteratorWithIndex no longer dereferences its null image pointer.
These iterators have no superclass that already declares the type aliases, and m_Image is a WeakPointer, not a smart pointer.
Extends the iterator conversion tests to TIterator<const TImage>: it is reached from the writable iterator and converts to and from the read-only name, no writable iterator is built from or derives from a read-only one, and the iterators compare across these names. The indexed and exclusion iterators keep ImageIteratorDimension and their constructors from indexed iterators over const images.
Checks that Set() exists for a non-const image and not for a const image, for the image, reverse, indexed, line, path, reflective, frequency, and flood-filled iterators; that an assignable Value() follows the same rule for the image, reverse, and indexed iterators; and that the read-only reverse iterators no longer provide Set().
Checks class template argument deduction from raw pointers to const images, that the read-only reverse iterator walks a region backward, that a reflective iterator keeps its state when converted to an iterator over a const image, and that a random non-repeating iterator over a const image owns its permutation.
Explains which iterator names now select access by the constness of the image type, what no longer compiles, and how downstream code adapts.
994865e to
f3d5cef
Compare
|
Force-push What changed
Still open: "ENH: Select ImageIteratorWithIndex access by image constness" fails #7135's exclusion-iterator constructibility check; a separate push will fix it. Not changed here: |
Closes #6141 and fixes #7003: the image iterators now take their access from the constness of the image type, so
XxxIterator<const ImageType>has noSet()and no writableValue(), and none of them needsconst_cast. Supersedes #7021 (its commits are here, authored by @mymonin) and #7117.Built on #7135, which is built on #7068; both must merge first. Their five commits come first here, unchanged; review from "STYLE: Remove the writable ImageIterator subclass" onward. #7135 carries the bug fixes and the tests that hold on
main; this PR extends those tests to iterators overconstimages.Commit layout for review. Most commits need no careful reading:
STYLE:commits that do not build alone: delete the writable subclass files,.hxxincluded (pure deletion),git mvtheConstfiles onto the writable names (renamed without changes), and rename the class identifiers (the body gives theperlcommand that reproduces it).STYLE:commits (= defaultcopy operations, stale comments), theENH: Test …commits, and the guide.The commits that change behavior, each small and compiling on its own:
Set()/Value(),m_Bufferconstness, the derivedImageConstIteratordetail::IsImageIteratorConvertible_voperator++/--intoImageReverseIteratorDesign
ImageRegionIterator<TImage>derives fromImageIterator<TImage>, and pixel pointers areconstexactly whenTImageisconst, so writes need no cast.Set()and non-constValue()are removed forconst TImagewith SFINAE.ImageRegionConstIterator<T>is a thin class deriving fromImageRegionIterator<const T>, with deduction guides forSmartPointer,ConstPointer, and raw pointers. Each header provides both names; theConstheaders remain as one-line includes, and the.hxxfiles of removed classes are deleted, since only their headers included them.detail::IsImageIteratorConvertible_vstates the allowed conversions: same image type, never droppingconst. Comparisons require the same image type, with or withoutconst.ImageReverseIterator<T>carries the row spans andoperator++/--(onmainit had them throughImageRegionReverseConstIterator<T>), soImageReverseConstIterator<T>gains them;ImageRegionReverseIterator<T>derives from it and adds only constructors.SliceIterator, and theRLEImageiterator specializations.API changes
Listed in the ITK 6 migration guide (last commit). Removed, by design:
constimage (const-qualified images can be modified viaitk::ImageRegionIterator<const ImageType>#7003), including the publicImageReverseConstIterator::Set().XxxIterator<T>toXxxConstIterator<T>base-class relation:Superclasschanges, and a non-constXxxConstIterator<T> &no longer accepts anXxxIterator<T>.Also: the frequency layout iterators initialize
m_ActualXDimensionIsOdd. The reflective copy, random non-repeating copy, andPathIterator::Value()fixes are in #7135. Kept from ITK 5:ImageIteratorDimensionand construction of the exclusion and frequency iterators from a plainImageIteratorWithIndex.Testing
ExclusionIteratorConstructibleFromImageIteratorWithIndexcheck; the next ENH commit builds. Every other commit expected to build compiles the five iterator test sources with no warnings. The refactor commit now carries the same-image comparison constraint, so it passes BUG: Fix iterator copy and PathIterator::Value() bugs, and test iterator access #7135'sHaveConstNonConstComparisonscheck.HasSetchecks now cover every converted iterator, including the frequency, reflective,PathIterator, and flood-filled ones.Module_RLEImageON);ITKCommon,ITKDistanceMap,ITKImageFrequency,ITKPath, andRLEImagetests: 872/872 pass. The only warnings are the existing ones in the IsotropicWavelets and RANSAC remote modules.pre-commit run --all-filespasses at the tip,git diff --checkpasses on every commit, and every rename commit equals itsperlrule applied to its parent.AI assistance (Claude Code) rebuilt the commit series with scripts kept for review and ran the checks; the author reviewed the changes.