How to address const correctness build issues associated with ITKUltrasound module ?

Issues are summarized in https://github.com/KitwareMedical/ITKUltrasound/pull/198 and also copied below for convenience.

These are errors reported when building SlicerITKUltrasound based of PR SlicerITKUltrasound#78

In file included from /home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingStrainWindowBlockAffineTransformCommand.h:105,
                 from /home/jcfr/Projects/SlicerITKUltrasound/GenerateDisplacementFromTimeSeries/GenerateDisplacementFromTimeSeries.cxx:38:
/home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingStrainWindowBlockAffineTransformCommand.hxx: In instantiation of ‘void itk::BlockMatching::StrainWindowBlockAffineTransformCommand<TStrainWindowDisplacemenCalculator, TBlockAffineTransformMetricImageFilter, TStrainImageFilter>::Execute(const itk::Object*, const itk::EventObject&) [with TStrainWindowDisplacemenCalculator = itk::BlockMatching::StrainWindowDisplacementCalculator<itk::Image<float, 2>, itk::Image<itk::Vector<float, 2>, 2>, float>; TBlockAffineTransformMetricImageFilter = itk::BlockMatching::BlockAffineTransformMetricImageFilter<itk::Image<unsigned char, 2>, itk::Image<unsigned char, 2>, itk::Image<float, 2>, float>; TStrainImageFilter = itk::StrainImageFilter<itk::Image<itk::Vector<float, 2>, 2>, float, float>]’:
/home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingStrainWindowBlockAffineTransformCommand.hxx:49:1:   required from here
/home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingStrainWindowBlockAffineTransformCommand.hxx:73:5: error: invalid conversion from ‘const OutputImageType*’ {aka ‘const itk::Image<itk::SymmetricSecondRankTensor<float, 2>, 2>*’} to ‘itk::BlockMatching::BlockAffineTransformMetricImageFilter<itk::Image<unsigned char, 2>, itk::Image<unsigned char, 2>, itk::Image<float, 2>, float>::StrainImageType*’ {aka ‘itk::Image<itk::SymmetricSecondRankTensor<float, 2>, 2>*’} [-fpermissive]
   73 |     m_BlockAffineTransformMetricImageFilter->SetStrainImage(strainWindower->GetStrainImageFilter()->GetOutput());
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |     |
      |     const OutputImageType* {aka const itk::Image<itk::SymmetricSecondRankTensor<float, 2>, 2>*}
In file included from /home/jcfr/Projects/Slicer-Release/ITK/Modules/IO/ImageBase/include/itkImageFileReaderException.h:22,
                 from /home/jcfr/Projects/Slicer-Release/ITK/Modules/IO/ImageBase/include/itkImageFileReader.h:20,
                 from /home/jcfr/Projects/SlicerITKUltrasound/GenerateDisplacementFromTimeSeries/GenerateDisplacementFromTimeSeries.cxx:19:
/home/jcfr/Projects/Slicer-Release/ITK/Modules/Core/Common/include/itkMacro.h:1097:33: note:   initializing argument 1 of ‘void itk::BlockMatching::BlockAffineTransformMetricImageFilter<TFixedImage, TMovingImage, TMetricImage, TStrainValueType>::SetStrainImage(itk::BlockMatching::BlockAffineTransformMetricImageFilter<TFixedImage, TMovingImage, TMetricImage, TStrainValueType>::StrainImageType*) [with TFixedImage = itk::Image<unsigned char, 2>; TMovingImage = itk::Image<unsigned char, 2>; TMetricImage = itk::Image<float, 2>; TStrainValueType = float; itk::BlockMatching::BlockAffineTransformMetricImageFilter<TFixedImage, TMovingImage, TMetricImage, TStrainValueType>::StrainImageType = itk::Image<itk::SymmetricSecondRankTensor<float, 2>, 2>]’
 1097 |   virtual void Set##name(type * _arg)                  \
/home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingBlockAffineTransformMetricImageFilter.h:104:3: note: in expansion of macro ‘itkSetObjectMacro’
  104 |   itkSetObjectMacro(StrainImage, StrainImageType);
      |   ^~~~~~~~~~~~~~~~~
In file included from /home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingStrainWindowBlockAffineTransformCommand.h:105,
                 from /home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingDisplacementPipeline.h:42,
                 from /home/jcfr/Projects/SlicerITKUltrasound/GenerateDisplacementFromFrames/GenerateDisplacementFromFrames.cxx:25:
/home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingStrainWindowBlockAffineTransformCommand.hxx: In instantiation of ‘void itk::BlockMatching::StrainWindowBlockAffineTransformCommand<TStrainWindowDisplacemenCalculator, TBlockAffineTransformMetricImageFilter, TStrainImageFilter>::Execute(const itk::Object*, const itk::EventObject&) [with TStrainWindowDisplacemenCalculator = itk::BlockMatching::StrainWindowDisplacementCalculator<itk::Image<float, 2>, itk::Image<itk::Vector<float, 2>, 2>, float>; TBlockAffineTransformMetricImageFilter = itk::BlockMatching::BlockAffineTransformMetricImageFilter<itk::Image<float, 2>, itk::Image<float, 2>, itk::Image<float, 2>, float>; TStrainImageFilter = itk::StrainImageFilter<itk::Image<itk::Vector<float, 2>, 2>, float, float>]’:
/home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingStrainWindowBlockAffineTransformCommand.hxx:49:1:   required from here
/home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingStrainWindowBlockAffineTransformCommand.hxx:73:5: error: invalid conversion from ‘const OutputImageType*’ {aka ‘const itk::Image<itk::SymmetricSecondRankTensor<float, 2>, 2>*’} to ‘itk::BlockMatching::BlockAffineTransformMetricImageFilter<itk::Image<float, 2>, itk::Image<float, 2>, itk::Image<float, 2>, float>::StrainImageType*’ {aka ‘itk::Image<itk::SymmetricSecondRankTensor<float, 2>, 2>*’} [-fpermissive]
   73 |     m_BlockAffineTransformMetricImageFilter->SetStrainImage(strainWindower->GetStrainImageFilter()->GetOutput());
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |     |
      |     const OutputImageType* {aka const itk::Image<itk::SymmetricSecondRankTensor<float, 2>, 2>*}
In file included from /home/jcfr/Projects/Slicer-Release/ITK/Modules/IO/ImageBase/include/itkImageFileReaderException.h:22,
                 from /home/jcfr/Projects/Slicer-Release/ITK/Modules/IO/ImageBase/include/itkImageFileReader.h:20,
                 from /home/jcfr/Projects/SlicerITKUltrasound/GenerateDisplacementFromFrames/GenerateDisplacementFromFrames.cxx:19:
/home/jcfr/Projects/Slicer-Release/ITK/Modules/Core/Common/include/itkMacro.h:1097:33: note:   initializing argument 1 of ‘void itk::BlockMatching::BlockAffineTransformMetricImageFilter<TFixedImage, TMovingImage, TMetricImage, TStrainValueType>::SetStrainImage(itk::BlockMatching::BlockAffineTransformMetricImageFilter<TFixedImage, TMovingImage, TMetricImage, TStrainValueType>::StrainImageType*) [with TFixedImage = itk::Image<float, 2>; TMovingImage = itk::Image<float, 2>; TMetricImage = itk::Image<float, 2>; TStrainValueType = float; itk::BlockMatching::BlockAffineTransformMetricImageFilter<TFixedImage, TMovingImage, TMetricImage, TStrainValueType>::StrainImageType = itk::Image<itk::SymmetricSecondRankTensor<float, 2>, 2>]’
 1097 |   virtual void Set##name(type * _arg)                  \
/home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingBlockAffineTransformMetricImageFilter.h:104:3: note: in expansion of macro ‘itkSetObjectMacro’
  104 |   itkSetObjectMacro(StrainImage, StrainImageType);
      |   ^~~~~~~~~~~~~~~~~
In file included from /home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingOptimizingInterpolationDisplacementCalculator.h:202,
                 from /home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingDisplacementPipeline.h:39,
                 from /home/jcfr/Projects/SlicerITKUltrasound/GenerateDisplacementFromFrames/GenerateDisplacementFromFrames.cxx:25:
/home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingOptimizingInterpolationDisplacementCalculator.hxx: In instantiation of ‘void itk::BlockMatching::OptimizingInterpolationDisplacementCalculator<TMetricImage, TDisplacementImage, TCoordRep>::SetMetricImagePixel(const PointType&, const IndexType&, itk::BlockMatching::OptimizingInterpolationDisplacementCalculator<TMetricImage, TDisplacementImage, TCoordRep>::MetricImageType*) [with TMetricImage = itk::Image<float, 2>; TDisplacementImage = itk::Image<itk::Vector<float, 2>, 2>; TCoordRep = double; itk::BlockMatching::OptimizingInterpolationDisplacementCalculator<TMetricImage, TDisplacementImage, TCoordRep>::PointType = itk::Point<double, 2>; itk::BlockMatching::OptimizingInterpolationDisplacementCalculator<TMetricImage, TDisplacementImage, TCoordRep>::IndexType = itk::Index<2>; itk::BlockMatching::OptimizingInterpolationDisplacementCalculator<TMetricImage, TDisplacementImage, TCoordRep>::MetricImageType = itk::Image<float, 2>]’:
/home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingOptimizingInterpolationDisplacementCalculator.hxx:41:1:   required from here
/home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingOptimizingInterpolationDisplacementCalculator.hxx:95:5: error: passing ‘const InterpolatorType’ {aka ‘const itk::InterpolateImageFunction<itk::Image<float, 2>, double>’} as ‘this’ argument discards qualifiers [-fpermissive]
   95 |     m_CostFunction->GetInterpolator()->SetInputImage(metricImage);
      |     ^~~~~~~~~~~~~~
In file included from /home/jcfr/Projects/Slicer-Release/ITK/Modules/Core/ImageFunction/include/itkImageFunction.h:229,
                 from /home/jcfr/Projects/Slicer-Release/ITK/Modules/Core/ImageFunction/include/itkInterpolateImageFunction.h:21,
                 from /home/jcfr/Projects/Slicer-Release/ITK/Modules/Core/ImageFunction/include/itkWindowedSincInterpolateImageFunction.h:23,
                 from /home/jcfr/Projects/SlicerITKUltrasound-Release/ITKUltrasound/include/itkBlockMatchingDisplacementPipeline.h:26,
                 from /home/jcfr/Projects/SlicerITKUltrasound/GenerateDisplacementFromFrames/GenerateDisplacementFromFrames.cxx:25:
/home/jcfr/Projects/Slicer-Release/ITK/Modules/Core/ImageFunction/include/itkImageFunction.hxx:57:1: note:   in call to ‘void itk::ImageFunction<TInputImage, TOutput, TCoordRep>::SetInputImage(const InputImageType*) [with TInputImage = itk::Image<float, 2>; TOutput = double; TCoordRep = double; itk::ImageFunction<TInputImage, TOutput, TCoordRep>::InputImageType = itk::Image<float, 2>]’
   57 | ImageFunction<TInputImage, TOutput, TCoordRep>::SetInputImage(const InputImageType * ptr)
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

cc: @dzenanz @matt.mccormick

To follow up, the issue has been addressed adding relevant const_cast and switching to use itkSetConstObjectMacro

diff --git a/include/itkBlockMatchingBlockAffineTransformMetricImageFilter.h b/include/itkBlockMatchingBlockAffineTransformMetricImageFilter.h
index 18d4ded..bdd20e7 100644
--- a/include/itkBlockMatchingBlockAffineTransformMetricImageFilter.h
+++ b/include/itkBlockMatchingBlockAffineTransformMetricImageFilter.h
@@ -79,7 +79,7 @@ public:
 
   /** Type of the strain image. */
   using StrainImageType = Image<SymmetricSecondRankTensor<TStrainValueType, ImageDimension>, ImageDimension>;
-  using StrainImagePointerType = typename StrainImageType::Pointer;
+  using StrainImagePointerType = typename StrainImageType::ConstPointer;
   using StrainInterpolatorType = LinearInterpolateImageFunction<StrainImageType, double>;
 
   /** Type of the transform. */
@@ -101,7 +101,7 @@ public:
   itkGetConstObjectMacro(MetricImageFilter, Superclass);
 
   /** Set/Get the strain image used to modify the fixed image block. */
-  itkSetObjectMacro(StrainImage, StrainImageType);
+  itkSetConstObjectMacro(StrainImage, StrainImageType);
   itkGetConstObjectMacro(StrainImage, StrainImageType);
 
 protected:
diff --git a/include/itkBlockMatchingOptimizingInterpolationDisplacementCalculator.hxx b/include/itkBlockMatchingOptimizingInterpolationDisplacementCalculator.hxx
index d65cad7..fa751a5 100644
--- a/include/itkBlockMatchingOptimizingInterpolationDisplacementCalculator.hxx
+++ b/include/itkBlockMatchingOptimizingInterpolationDisplacementCalculator.hxx
@@ -92,7 +92,7 @@ OptimizingInterpolationDisplacementCalculator<TMetricImage, TDisplacementImage,
     for (unsigned int i = 0; i < ImageDimension; i++)
       parameters[i] += 0.1;
     m_CostFunction->Initialize(parameters);
-    m_CostFunction->GetInterpolator()->SetInputImage(metricImage);
+    const_cast<InterpolatorType*>(m_CostFunction->GetInterpolator())->SetInputImage(metricImage);
     m_Optimizer->StartOptimization();
 
     parameters = m_Optimizer->GetCurrentPosition();

Is there no way to get “modifiable” access to the interpolator? Possibly by something like m_CostFunction->GetModifiableInterpolator()?

const_cast should be used reluctantly, of course, as it breaks const-correctness, and it may in some cases cause undefined behavior.

My two cents, Niels