可变参数模板在什么时候被认为是“声明的”?这在 clang++ 3.4 下编译,但不在 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);
}
显然 g++ 不会匹配尾随返回类型中的函数本身。g++ 4.8.2 的错误是:
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...));
^
附录:如果我删除可变参数模板的声明,clang++ 和 g++ 都会出错。
补充2:我看到之前已经问过类似的问题。我想这里真正的问题是为什么它适用于一个编译器而不是另一个。此外,我可以通过使用 sum() 的非原始参数在 POI 处强制 ADL 使其与 g++ 一起使用。
附录 3:这适用于 clang++ 和 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());
}