http://coliru.stacked-crooked.com/a/5d16c7e740a31a02
#include <iostream>
template<typename T> void P(T x) { std::cout << x; }
void foo(char a) {
P(3);
P(a);
}
template <typename... A>
void foo(int a, A... args) {
foo(args...);
P(a);
}
template <typename... A>
void foo(char a, A... args) {
P(a);
foo(args...);
}
int main()
{
foo('1', '2', 48, '4', '5');
}
//1243548 My result (VS2015)
//12355248 correct result (clang, gcc)
&#34;如何纠正&#34;结果生成了吗?
答案 0 :(得分:1)
这里的诀窍是int
的{{1}}重载不知道foo
重载,因为它还没有被看到,因此该级别的调用变为递归本身:
char
拨打template <typename... A>
void foo(int a, A... args) { /* only ever calls itself and above*/}
foo(48, '4', '5')
被解释为foo(int a, A...)
,那么将会追加chars
的其他来电!
因此,您将按预期获得初始int
,但之后您只会为字符打印ASCII值,因此您将获得12
的值52
,'4'
的值53
。 Clang和gcc是正确的;您的Visual Studio版本正在打印错误的值。 (I was able to reproduce with VC 19.00.23506)
这是一个呼叫追踪(instrumented with some help from C++17):
'5'
现在,如果我们移动你的代码以便我们转发声明我们的模板(这总是一个好习惯),你就会得到你想要的行为:
Called foo(char a, A... args) with 1,2,48,4,5
Called P(T) with 1
Called foo(char a, A... args) with 2,48,4,5
Called P(T) with 2
Called foo(int a, A... args) with 48,4,5
Called foo(int a, A... args) with 52,5
Called foo(char a) with 5
Called P(T) with 3
Called P(T) with 5
Called P(T) with 52
Called P(T) with 48
然后,您将获得所需的输出。这是该版本(demo)的堆栈跟踪:
template<typename T>
void P(T x);
template <typename... A>
void foo(int a, A... args);
template <typename... A>
void foo(char a, A... args);
// actual definitions below...