How to SFINAE to include a member function returning `auto`

In a template metaprogram, you can use SFINAE on return type to select a specific template member function, i.e.

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

      

However, this will not work if the function _sum()

in question ( in the above example) has an auto-detected return type, such _func()

as in this example

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

      

What else can you do to get SFINAE here?

+3


source to share


1 answer


Following on from David Rodriguez-Dribe, the following code worked as intended:

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

      



strictly speaking, we also need to make sure that the binary operator op

returns the correct type. For simplicity and brevity of the answer, I leave this for the reader to understand ...

+1


source







All Articles