如何 SFINAE 启用返回“auto”的成员函数

how to SFINAE for enabling member function returning `auto`

本文关键字:成员 函数 auto SFINAE 启用 返回 如何      更新时间:2023-10-16

在模板元编程中,可以在返回类型上使用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?

在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返回正确的类型。为了答案的简单和简洁,我把它留给读者弄清楚......