为什么在这种情况下会出现 "is not a constant expression" 错误? (模板)

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

我正在尝试用 C++ 为我的 ITK 图像实现某种 numpy.where()。 ITK 的方式似乎是与函子。我对模板不是很有经验,所以我的整个方法可能有缺陷,但我的做法是:

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;
}

当我尝试调用此 where 函数时: auto img = where<MASK_IMAGE_TYPE>(my_image, 0, 1, 0);,我收到以下错误:

: 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’

我想我知道这样的错误可能是由于编译类型的类型不确定性造成的,但在这种情况下我不明白它是从哪里来的。

您有很多不必要的模板参数。你可以按照它在相应测试中完成的方式进行操作。定义您的 function, set it via filter->SetFunctor() 并调用 Update().

按照建议,更正后的代码版本为:

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

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>>::New();
    filter->SetFunctor(WhereFunctor<typename T::PixelType>(value, if_equal, if_n_equal));
    filter->SetInPlace(false);
    filter->SetInput(img);
    filter->Update();
    typename T::Pointer ret_img = filter->GetOutput();
    return ret_img;
}