otbVariadicInputsImageFilter.h 5.16 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef otb_VariadicInputsImageFilter_h
#define otb_VariadicInputsImageFilter_h

Julien Michel's avatar
Julien Michel committed
23 24
#include "itkImageSource.h"

25 26
namespace otb {

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
/**
 * \brief Base class for image filter with variadic inputs.
 *
 * This filter act as a base class for all filters that will take
 * several input images with different types and produce an output
 * image.
 * 
 * Type for each input is taken from the variadic template parameter
 * TInputs.
 * 
 * Inputs get be set/get with SetVariadicInput<N>() and
 * GetVariadicInput<N>(), when N is the index (first input is 0) of
 * the input. This is resolved at compile time: you can not call 
 * SetVariadicInput<N>() with an argument not matching the Nth input
 * type (it will lead to type mismatch compilation error).
 * 
 * Alternatively, you can call SetVariadicInputs() with all the input
 * image in the same order as in the template parameters.
 *
 * Last, there is a macro that generates SetInput1() ... SetInput10()
 * (iff the number of varidic input types is large enough) for
 * backward compatibility.
 * 
 */
51 52 53 54 55 56 57
template<class TOuptut, class ... TInputs> class VariadicInputsImageFilter : public itk::ImageSource<TOuptut>
{
public:
  using Self = VariadicInputsImageFilter<TOuptut, TInputs...>;
  using Pointer =  itk::SmartPointer<Self>;
  using ConstPointer = itk::SmartPointer<const Self>;
  using Superclass = itk::ImageSource<TOuptut>;
58
  
59
  using InputTypesTupleType = std::tuple<TInputs...>;
60 61
  
  template <size_t I> using InputImageType = typename std::tuple_element<I,InputTypesTupleType>::type;
62 63
  static constexpr size_t NumberOfInputs = std::tuple_size<InputTypesTupleType>::value; 

64
  // Good old new macro
65
  itkNewMacro(Self);
66 67 68 69

  /**
   * \param Set the Ith input
   */
70
  template <std::size_t I> void SetVariadicInput(const typename std::tuple_element<I,InputTypesTupleType>::type * inputPtr)
71
  {
72
    static_assert(std::tuple_size<InputTypesTupleType>::value>I,"Template value I is out of range.");
73
    this->SetNthInput(I,const_cast<typename std::tuple_element<I,InputTypesTupleType>::type *>(inputPtr));
74
  }
75
  
76
#define DefineLegacySetInputMacro(n)                                                                               \
77 78
  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)                                           \
79
  {                                                                                                                \
80
    this->template SetVariadicInput<n-1>(img);                                                                             \
81 82 83 84 85 86 87 88 89 90 91 92 93 94
  }

  // The following defines legacy setters SetInput1()
  // ... SetInput10(), only if the number of input type is sufficient
  DefineLegacySetInputMacro(1);
  DefineLegacySetInputMacro(2);
  DefineLegacySetInputMacro(3);
  DefineLegacySetInputMacro(4);
  DefineLegacySetInputMacro(5);
  DefineLegacySetInputMacro(6);
  DefineLegacySetInputMacro(7);
  DefineLegacySetInputMacro(8);
  DefineLegacySetInputMacro(9);
  DefineLegacySetInputMacro(10);
95 96

#undef DefineLegacySetInputMacro
97 98 99 100

  /**
   * \return the Ith variadic input
   */
101
  template <std::size_t I> const typename std::tuple_element<I,InputTypesTupleType>::type * GetVariadicInput()
102
  {
103
    static_assert(std::tuple_size<InputTypesTupleType>::value>I,"Template value I is out of range.");
104 105 106 107
    using ImageType = typename std::tuple_element<I,InputTypesTupleType>::type;
    return dynamic_cast<const ImageType *>(this->GetInput(I));
  }

108 109 110
  /**
   * \param inputs A vararg list of inputs 
   */
111
  void SetVariadicInputs(TInputs*... inputs)
112 113 114 115 116
  {
    auto inTuple = std::make_tuple(inputs...);
    SetInputsImpl(inTuple,std::make_index_sequence<sizeof...(inputs)>{});
  }

117 118 119
  /**
   * \return A tuple with all inputs
   */
120
  auto GetVariadicInputs()
121 122 123 124
  {
    return GetInputsImpl(std::make_index_sequence<sizeof...(TInputs)>{});
  }

125 126 127 128 129 130 131 132 133 134 135
protected:
  VariadicInputsImageFilter()
  {
    this->SetNumberOfRequiredInputs(sizeof...(TInputs));
  };
  
  ~VariadicInputsImageFilter() = default;
  
private:
  template<class Tuple, size_t...Is> auto SetInputsImpl(Tuple& t, std::index_sequence<Is...>)
  {
136
    return std::initializer_list<int>{(this->SetVariadicInput<Is>(std::get<Is>(t)),0)...};
137
  }
138 139 140

  template <size_t...Is> auto GetInputsImpl(std::index_sequence<Is...>)
  {
141
    return std::make_tuple(this->GetVariadicInput<Is>()...);
142
  }
143 144 145 146 147 148 149 150
  
  VariadicInputsImageFilter(const Self&) = delete;
  void operator=(const Self&) = delete;
};

}

#endif