c++templatesitk

Why do I get "is not a constant expression" error in this case ? (templates)


I am trying to implement some kind of numpy.where() for my ITK images in C++. ITK's way seems to be with Functors. I am not very experienced with templates, so my whole approach might be flawed, but here is my go:

using MASK_IMAGE_TYPE = itk::Image<unsigned short, 3>;

template<class T, T value, T if_equal, T if_n_equal> class WhereFunctor
{
private:
    T v = value;
    T e = if_equal;
    T n = if_n_equal;
public:
    WhereFunctor() = default;
    ~WhereFunctor() = default;
    inline T operator()(const T& in_value)
    {
        return in_value == value ? if_equal : if_n_equal;
    }
};

template<typename T> typename T::Pointer where(
        typename T::Pointer& img,
        typename T::PixelType value,
        typename T::PixelType if_equal,
        typename T::PixelType if_n_equal)
{
    auto filter = itk::UnaryFunctorImageFilter<T, T, WhereFunctor<typename T::PixelType, value, if_equal, if_n_equal>>::New();
    filter->SetInPlace(false);
    filter->SetInput(img);
    filter->Update();
    typename T::Pointer ret_img = filter->GetOutput();
    return ret_img;
}

When I try to call this where function with: auto img = where<MASK_IMAGE_TYPE>(my_image, 0, 1, 0);, I get the following error:

: In instantiation of ‘typename T::Pointer where(typename T::Pointer&, typename T::PixelType, typename T::PixelType, typename T::PixelType) [with T = itk::Image<short unsigned int, 3>; typename T::Pointer = itk::SmartPointer<itk::Image<short unsigned int, 3> >; typename T::PixelType = short unsigned int]’:
:23:55:   required from here
:58:124: error: ‘value’ is not a constant expression
   58 |     auto filter = itk::UnaryFunctorImageFilter<T, T, WhereFunctor<typename T::PixelType, value, if_equal, if_n_equal>>::New();
      |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
:58:124: note: in template argument for type ‘short unsigned int’
:58:124: error: ‘if_equal’ is not a constant expression
:58:124: note: in template argument for type ‘short unsigned int’
:58:124: error: ‘if_n_equal’ is not a constant expression
:58:124: note: in template argument for type ‘short unsigned int’

I think I understand that such an error can be due to type indeterminacy at compile type, but in this case I do not understand where it comes from.


Solution

  • You have needlessly many template parameters. You could follow the way it is done in a corresponding test. Define your function, set it via filter->SetFunctor() and call Update().