At what point is a variadic template considered "declared"? This compiles under clang++ 3.4, but not under g++ 4.8.2.
template <typename T>
const T &sum(const T &v) { return v; }
template <typename T, typename ... Ts>
auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...));
template <typename T, typename ... Ts>
auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...)) {
return v + sum(params...);
}
int main() {
sum(1, 2, 3);
}
Apparently g++ won't match the function itself in the trailing return type. The error from g++ 4.8.2 is:
sum.cpp: In function 'int main()':
sum.cpp:13:16: error: no matching function for call to 'sum(int, int, int)'
sum(1, 2, 3);
^
sum.cpp:13:16: note: candidates are:
sum.cpp:2:10: note: template<class T> const T& sum(const T&)
const T &sum(const T &v) { return v; }
^
sum.cpp:2:10: note: template argument deduction/substitution failed:
sum.cpp:13:16: note: candidate expects 1 argument, 3 provided
sum(1, 2, 3);
^
sum.cpp:8:6: note: template<class T, class ... Ts> decltype ((v + sum(sum::params ...))) sum(const T&, const Ts& ...)
auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...)) {
^
sum.cpp:8:6: note: template argument deduction/substitution failed:
sum.cpp: In substitution of 'template<class T, class ... Ts> decltype ((v + sum(sum::params ...))) sum(const T&, const Ts& ...) [with T = int; Ts = {int, int}]':
sum.cpp:13:16: required from here
sum.cpp:5:74: error: no matching function for call to 'sum(const int&, const int&)'
auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...));
^
sum.cpp:5:74: note: candidate is:
sum.cpp:2:10: note: template<class T> const T& sum(const T&)
const T &sum(const T &v) { return v; }
^
sum.cpp:2:10: note: template argument deduction/substitution failed:
sum.cpp:5:74: note: candidate expects 1 argument, 2 provided
auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...));
^
Addendum: If I delete the declaration of the variadic template, both clang++ and g++ give errors.
Addedum 2: I see that a similar question has been asked before. I guess the real question here is why it works with one compiler and not the other. Also, I can make it work with g++ by forcing ADL at the POI by using non-primitive arguments to sum().
Addendum 3: This works under both clang++ and g++:
class A {
};
A operator+(const A &, const A &) {
return A();
}
template <typename T>
const T &sum(const T &v) { return v; }
/*
template <typename T, typename ... Ts>
auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...));
*/
template <typename T, typename ... Ts>
auto sum(const T &v, const Ts & ... params) -> decltype(v + sum(params...)) {
return v + sum(params...);
}
int main() {
//sum(1, 2, 3);
sum(A(), A(), A());
}