From d8dffd444390bfa40f77014942e67a23ffe31e18 Mon Sep 17 00:00:00 2001
From: Julien Michel <julien.michel@cnes.fr>
Date: Fri, 16 Nov 2018 16:19:33 +0100
Subject: [PATCH] ENH: Rename (VInput -> VariadicInput) and add more checks

---
 .../Functor/include/otbFunctorImageFilter.h   |  4 +-
 .../Functor/include/otbFunctorImageFilter.hxx |  6 +-
 .../include/otbVariadicInputsImageFilter.h    | 14 ++--
 .../Functor/test/otbFunctorImageFilter.cxx    | 78 ++++++++++++-------
 4 files changed, 62 insertions(+), 40 deletions(-)

diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.h b/Modules/Core/Functor/include/otbFunctorImageFilter.h
index 1a7daba4ec..3af0e552c3 100644
--- a/Modules/Core/Functor/include/otbFunctorImageFilter.h
+++ b/Modules/Core/Functor/include/otbFunctorImageFilter.h
@@ -83,7 +83,7 @@ template <class T> struct IsSuitableType<itk::VariableLengthVector<T>> {
 };
 
 /// Unwrap FixedArray
-template <class T> struct IsSuitableType<itk::FixedArray<T>> {
+template <class T, size_t N> struct IsSuitableType<itk::FixedArray<T,N>> {
   static constexpr bool value = IsSuitableType<T>::value;
 };
 
@@ -218,7 +218,7 @@ template <typename C, typename R, typename... T> struct FunctorFilterSuperclassH
  * - returns T or itk::VariableLengthVector<T>, with T a scalar type
  *
  * The returned filter is ready to use. Inputs can be set through the
- * SetVInputs() method (see VariadicInputsImageFilter class for
+ * SetVariadicInputs() method (see VariadicInputsImageFilter class for
  * details)
  * 
  * \param f the Functor to build the filter from
diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx
index edfea3c78d..f0a1dc9100 100644
--- a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx
+++ b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx
@@ -196,7 +196,7 @@ FunctorImageFilter<TFunction>
   // Propagate to each variadic inputs, including possible radius
   // TODO: For now all inputs are padded with the radius, even if they
   // are not neighborhood based
-  functor_filter_details::SetInputRequestedRegions(this->GetVInputs(),requestedRegion, m_Radius);
+  functor_filter_details::SetInputRequestedRegions(this->GetVariadicInputs(),requestedRegion, m_Radius);
 }
 
 template <class TFunction>
@@ -207,7 +207,7 @@ FunctorImageFilter<TFunction>::GenerateOutputInformation()
   Superclass::GenerateOutputInformation();
 
   // Get All variadic inputs
-  auto inputs = this->GetVInputs();
+  auto inputs = this->GetVariadicInputs();
 
   // Retrieve an array of number of components per input
   auto inputNbComps = functor_filter_details::GetNumberOfComponentsPerInput(inputs);
@@ -228,7 +228,7 @@ FunctorImageFilter<TFunction>
   itk::ImageScanlineIterator<OutputImageType> outIt(this->GetOutput(),outputRegionForThread);
   itk::ProgressReporter p(this,threadId,outputRegionForThread.GetNumberOfPixels());
 
-  auto inputIterators = functor_filter_details::MakeIterators(this->GetVInputs(),outputRegionForThread, m_Radius,InputHasNeighborhood{});
+  auto inputIterators = functor_filter_details::MakeIterators(this->GetVariadicInputs(),outputRegionForThread, m_Radius,InputHasNeighborhood{});
   
   while(!outIt.IsAtEnd())
     {
diff --git a/Modules/Core/Functor/include/otbVariadicInputsImageFilter.h b/Modules/Core/Functor/include/otbVariadicInputsImageFilter.h
index f66752e6f0..5ed4a29e85 100644
--- a/Modules/Core/Functor/include/otbVariadicInputsImageFilter.h
+++ b/Modules/Core/Functor/include/otbVariadicInputsImageFilter.h
@@ -42,7 +42,7 @@ public:
   
   itkNewMacro(Self);
   
-  template <std::size_t I> void SetVInput(const typename std::tuple_element<I,InputTypesTupleType>::type * inputPtr)
+  template <std::size_t I> void SetVariadicInput(const typename std::tuple_element<I,InputTypesTupleType>::type * inputPtr)
   {
     this->SetNthInput(I,const_cast<typename std::tuple_element<I,InputTypesTupleType>::type *>(inputPtr));
   }
@@ -51,7 +51,7 @@ public:
   template<typename Tuple = InputTypesTupleType, typename Check = typename std::enable_if<n<=std::tuple_size<Tuple>::value >::type> \
   void SetInput ## n(const typename std::tuple_element<n-1,Tuple>::type * img)                                           \
   {                                                                                                                \
-    this->template SetVInput<n-1>(img);                                                                             \
+    this->template SetVariadicInput<n-1>(img);                                                                             \
   }
 
   // The following defines legacy setters SetInput1()
@@ -69,19 +69,19 @@ public:
 
 #undef DefineLegacySetInputMacro
   
-  template <std::size_t I> const typename std::tuple_element<I,InputTypesTupleType>::type * GetVInput()
+  template <std::size_t I> const typename std::tuple_element<I,InputTypesTupleType>::type * GetVariadicInput()
   {
     using ImageType = typename std::tuple_element<I,InputTypesTupleType>::type;
     return dynamic_cast<const ImageType *>(this->GetInput(I));
   }
 
-  void SetVInputs(TInputs*... inputs)
+  void SetVariadicInputs(TInputs*... inputs)
   {
     auto inTuple = std::make_tuple(inputs...);
     SetInputsImpl(inTuple,std::make_index_sequence<sizeof...(inputs)>{});
   }
 
-  auto GetVInputs()
+  auto GetVariadicInputs()
   {
     return GetInputsImpl(std::make_index_sequence<sizeof...(TInputs)>{});
   }
@@ -97,12 +97,12 @@ protected:
 private:
   template<class Tuple, size_t...Is> auto SetInputsImpl(Tuple& t, std::index_sequence<Is...>)
   {
-    return std::initializer_list<int>{(this->SetVInput<Is>(std::get<Is>(t)),0)...};
+    return std::initializer_list<int>{(this->SetVariadicInput<Is>(std::get<Is>(t)),0)...};
   }
 
   template <size_t...Is> auto GetInputsImpl(std::index_sequence<Is...>)
   {
-    return std::make_tuple(this->GetVInput<Is>()...);
+    return std::make_tuple(this->GetVariadicInput<Is>()...);
   }
   
   VariadicInputsImageFilter(const Self&) = delete;
diff --git a/Modules/Core/Functor/test/otbFunctorImageFilter.cxx b/Modules/Core/Functor/test/otbFunctorImageFilter.cxx
index cf42cb22b5..44fe64ea55 100644
--- a/Modules/Core/Functor/test/otbFunctorImageFilter.cxx
+++ b/Modules/Core/Functor/test/otbFunctorImageFilter.cxx
@@ -39,26 +39,38 @@ template <typename T> struct TypesCheck
   using ScalarType                    = T;
   using ImageType                     = otb::Image<T>;
   using VectorType                    = itk::VariableLengthVector<ScalarType>;
+  using FixedArrayType                = itk::FixedArray<ScalarType,4>;
+  using RGBPixelType                  = itk::RGBPixel<ScalarType>;
+  using RGBAPixelType                 = itk::RGBAPixel<ScalarType>;
   using VectorImageType               = otb::VectorImage<ScalarType>;
   using NeighborhoodType              = itk::Neighborhood<ScalarType>;
   using VectorNeighborhoodType        = itk::Neighborhood<VectorType>;
-  
+
   // Test IsNeighborhood struct
-  static_assert(!otb::IsNeighborhood<ScalarType>::value,"");
-  static_assert(!otb::IsNeighborhood<VectorType>::value,"");
-  static_assert(otb::IsNeighborhood<NeighborhoodType>::value,"");
-  static_assert(otb::IsNeighborhood<VectorNeighborhoodType>::value,"");
-  static_assert(otb::IsNeighborhood<const NeighborhoodType &>::value,"");
-  static_assert(otb::IsNeighborhood<const VectorNeighborhoodType &>::value,"");
+  template <typename U> struct CheckIsNeighborhood
+  {
+    static constexpr bool value = !otb::IsNeighborhood<U>::value && otb::IsNeighborhood<itk::Neighborhood<U> >::value;
+  };
+    
+  static_assert(CheckIsNeighborhood<T>::value,"");
+  static_assert(CheckIsNeighborhood<itk::VariableLengthVector<T>>::value,"");
+  static_assert(CheckIsNeighborhood<itk::FixedArray<T,4>>::value,"");
+  static_assert(CheckIsNeighborhood<itk::RGBPixel<T>>::value,"");
+  static_assert(CheckIsNeighborhood<itk::RGBAPixel<T>>::value,"");
 
   // Test PixelTypeDeduction struct
-  static_assert(std::is_same<typename PixelTypeDeduction<ScalarType>::PixelType,ScalarType>::value,"");
-  static_assert(std::is_same<typename PixelTypeDeduction<VectorType>::PixelType,VectorType>::value,"");
-  static_assert(std::is_same<typename PixelTypeDeduction<NeighborhoodType>::PixelType,ScalarType>::value,"");
-  static_assert(std::is_same<typename PixelTypeDeduction<VectorNeighborhoodType>::PixelType,VectorType>::value,"");
-  static_assert(std::is_same<typename PixelTypeDeduction<const NeighborhoodType &>::PixelType,ScalarType>::value,"");
-  static_assert(std::is_same<typename PixelTypeDeduction<const VectorNeighborhoodType &>::PixelType,VectorType>::value,"");
+  template<typename U> struct CheckPixelTypeDeduction
+  {
+    static constexpr bool value = std::is_same<typename PixelTypeDeduction<U>::PixelType,U>::value
+      && std::is_same<typename PixelTypeDeduction<itk::Neighborhood<U>>::PixelType,U>::value;
+  };
 
+  static_assert(CheckPixelTypeDeduction<T>::value,"");
+  static_assert(CheckPixelTypeDeduction<itk::VariableLengthVector<T>>::value,"");
+  static_assert(CheckPixelTypeDeduction<itk::FixedArray<T,4>>::value,"");
+  static_assert(CheckPixelTypeDeduction<itk::RGBPixel<T>>::value,"");
+  static_assert(CheckPixelTypeDeduction<itk::RGBAPixel<T>>::value,"");
+  
   // Test ImageTypeDeduction struct
   static_assert(std::is_same<typename ImageTypeDeduction<ScalarType>::ImageType,ImageType>::value,"");
   static_assert(std::is_same<typename ImageTypeDeduction<VectorType>::ImageType,VectorImageType>::value,"");
@@ -102,10 +114,20 @@ template <typename T> struct TypesCheck
   static_assert(FilterType::NumberOfInputs == 1,"");
   static_assert(std::is_same<typename FilterType::template InputImageType<0>, InputImageType>::value, "");
 
-  filter->SetVInputs(in);
+  filter->SetVariadicInputs(in);
   filter->SetInput1(in);
-  filter->template SetVInput<0>(in); // template keyword to avoid C++ parse ambiguity
+  filter->template SetVariadicInput<0>(in); // template keyword to avoid C++ parse ambiguity
   filter->Update();
+
+  // Test with simple lambda
+  auto lambda = [] (const TIn &)
+                {
+                  TOut ret(1);
+                  return ret;
+                };
+  auto filterWithLambda = NewFunctorFilter(lambda,1, {{0,0}});
+  filterWithLambda->SetVariadicInputs(in);
+  filterWithLambda->Update();
   }
 
   TypesCheck()
@@ -264,14 +286,14 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) [])
 
   // Test VariadicInputsImageFilter
   auto filter = otb::VariadicInputsImageFilter<VectorImageType,VectorImageType,ImageType>::New();
-  filter->SetVInput<0>(vimage);
-  filter->SetVInput<1>(image);
+  filter->SetVariadicInput<0>(vimage);
+  filter->SetVariadicInput<1>(image);
 
   filter->SetInput1(vimage);
   filter->SetInput2(image);
 
-  filter->SetVInputs(vimage,image);
-  std::cout<<filter->GetVInput<0>()<< filter->GetVInput<1>()<<std::endl;
+  filter->SetVariadicInputs(vimage,image);
+  std::cout<<filter->GetVariadicInput<0>()<< filter->GetVariadicInput<1>()<<std::endl;
 
   
   // test FunctorImageFilter with a lambda
@@ -281,7 +303,7 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) [])
                  return scale*p;
                };
   auto filterLambda = NewFunctorFilter(Lambda1);
-  filterLambda->SetVInputs(image);
+  filterLambda->SetVariadicInputs(image);
   filterLambda->Update();
 
   // test FunctorImageFilter with a lambda that returns a
@@ -301,49 +323,49 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) [])
   // In this case, we use the helper function which allows to specify
   // the number of outputs
   auto filterLambda2  = NewFunctorFilter(Lambda2,vimage->GetNumberOfComponentsPerPixel(),{{3,3}});
-  filterLambda2->SetVInputs(image);
+  filterLambda2->SetVariadicInputs(image);
   filterLambda2->Update();
   
   // Test FunctorImageFilter with the VariadicConcatenate operator
   using ConcatFunctorType = Functor::VariadicConcatenate<double, double, itk::VariableLengthVector<double> >;
   auto concatenate = NewFunctorFilter(ConcatFunctorType{});
-  concatenate->SetVInputs(image,vimage);
+  concatenate->SetVariadicInputs(image,vimage);
   concatenate->Update();
   
   // Test FunctorImageFilter With VariadicAdd functor
   using AddFunctorType = Functor::VariadicAdd<double, double, double>;
   auto add = NewFunctorFilter(AddFunctorType{});
-  add->SetVInputs(image,image);
+  add->SetVariadicInputs(image,image);
   add->Update();
 
   // Test FunctorImageFilter with BandExtraction functor
   using ExtractFunctorType = BandExtraction<double,double>;
   ExtractFunctorType extractFunctor{1,2};
   auto extract = NewFunctorFilter(extractFunctor);
-  extract->SetVInputs(vimage);
+  extract->SetVariadicInputs(vimage);
   extract->Update();
   
   // Test FunctorImageFilter With Mean functor
   using MeanFunctorType = Mean<double,double>;
   auto median = NewFunctorFilter(MeanFunctorType{},{{2,2}});
-  median->SetVInputs(image);
+  median->SetVariadicInputs(image);
   median->Update();
 
   // Test FunctorImageFilter with MaxInEachChannel
   using MaxInEachChannelType = MaxInEachChannel<double>;
   auto maxInEachChannel = NewFunctorFilter(MaxInEachChannelType{},{{3,3}});
-  maxInEachChannel->SetVInputs(vimage);
+  maxInEachChannel->SetVariadicInputs(vimage);
   maxInEachChannel->Update();
 
   // Test FunctorImageFilter with Module (complex=
   using ModulusType = VectorModulus<double>;
   auto modulus = NewFunctorFilter(ModulusType{});
-  modulus->SetVInputs(cvimage);
+  modulus->SetVariadicInputs(cvimage);
   modulus->Update();
 
   auto LambdaComplex = [] (const std::complex<double> & in) {return std::arg(in);};
   auto argFilter = NewFunctorFilter(LambdaComplex);
-  argFilter->SetVInputs(cimage);
+  argFilter->SetVariadicInputs(cimage);
   argFilter->Update();
 
  return EXIT_SUCCESS;
-- 
GitLab