В шаблонном метапрограммировании можно использовать 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])); }
};
Что еще можно сделать, чтобы получить СФИНА здесь?
После 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
возвращает правильный тип. Для простоты и краткости ответа оставляю читателю понять, что …
Других решений пока нет …