3

在模板元编程中,可以在返回类型上使用 SFINAE 来选择某个模板成员函数,即

 template<int N> struct A {
   int sum() const noexcept
   { return _sum<N-1>(); }
 private:
   int _data[N];
   template<int I> typename std::enable_if< I,int>::type _sum() const noexcept
   { return _sum<I-1>() + _data[I]; }
   template<int I> typename std::enable_if<!I,int>::type _sum() const noexcept
   { return _data[I]; }
};

但是,如果有问题的函数(在上面的例子中)具有自动检测的返回类型,这将不起作用_sum(),例如_func()在这个例子中

template<int N> class A
{
   /* ... */
private:
  // how to make SFINAE work for _func() ?
  template<int I, typename BinaryOp, typename UnaryFunc>
  auto _func(BinaryOp op, UnaryFunc f) const noexcept -> decltype(f(_data[0]))
  { return op(_func<I-1>(op,f),f(_data[I])); }
};

还可以做些什么来获得 SFINAE?

4

1 回答 1

1

在 David Rodríguez - dribeas 之后,以下代码按预期工作:

template<int N> class A
{
  int min_abs() const noexcept
  {
    return _func<N-1>([](int x, int y)->int { return std::min(x,y); },
                      [](int x)->int { return std::abs(x); });
  }
private:
  int _data[N];

  template<int I, typename BinaryOp, typename UnaryFunc>
  auto _func(BinaryOp op, UnaryFunc f) const noexcept
    -> typename std::enable_if< I>,decltype(f(_data[0]))>::type
  { return op(_func<I-1>(op,f),f(_data[I])); }

  template<int I, typename BinaryOp, typename UnaryFunc>
  auto _func(BinaryOp op, UnaryFunc f) const noexcept
    -> typename std::enable_if<!I>,decltype(f(_data[0]))>::type
  { return f(_data[I]); }
};

严格来说,我们还必须确保二元运算符op返回正确的类型。为了答案的简单和简洁,我把它留给读者去弄清楚......

于 2013-01-29T18:22:12.113 回答