Поиск имени функции в конце типа возврата здесь,
template<typename T, typename... Args>
static auto sum(T n, Args... rest) -> decltype(n+sum(rest...))
выполняется в контексте непосредственно перед объявлением этого sum
, плюс через ADL (поиск в зависимости от аргумента).
И так как этот шаблон не виден через ADL в момент вызова для рассматриваемых типов, вполне допустимо, чтобы он не компилировался.
Старые компиляторы gcc, вероятно, использовали контекст объекта в дополнение к контекстам, которые они должны. Это разумная ошибка.
Вы можете легко это исправить:
struct Sum {
private:
template<typename T>
friend T summer(Sum, T n) {
return n;
}
template<typename T, typename... Args>
friend auto summer(Sum, T n, Args... rest) -> decltype(n+summer(Sum{},rest...)) {
return n + summer(Sum{},rest...);
}
public:
template<class...Args>
auto sum(Args...args)->decltype(summer(Sum{}, args...)){
return summer(Sum{}, args... );
}
};
здесь мы навязываем ADL некоторым личным друзьям. Это позволяет летним перегрузкам «видеть себя» в их типе конечного возврата.