2017-03-13 12 views
2
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) 

はどのように "正しい" 結果が生成されていますか?

+0

リンクコンパイラコードはC++ 14用で、質問にはC++ 11とマークされています。どちらですか? – AndyG

+0

また、リンクされたコードは正しいコードを生成します。あなたは理由の説明を探していますか?おそらく、失敗したコードを提供して、なぜそれが機能しないのかを教えてくれるでしょうか? – AndyG

+0

@AndyGリストされた私の結果は、私が把握できる出力です。 VS2015は私と同じ結果を出力します。はい、正しい結果がどのように生成されているか知りたいと思います。 – q0987

答えて

1

ここでのトリック、それはまだ見られていないので、そのレベルでの通話が自身に再帰的になるようfooint過負荷が、char過負荷についての考えを持っていないということです。だから、

template <typename... A> 
void foo(int a, A... args) { /* only ever calls itself and above*/} 

コールfoo(48, '4', '5')

charsintとして解釈されますfoo(int a, A...)への追加の呼び出しを再帰的になります!

期待通りだから、初期12を得るでしょうが、あなたは'4'ため52の値、および'5'ため53の値を取得しますので、あなたは、単に、文字のASCII値を印刷します。 Clangとgccは正しいです。 Visual Studioのバージョンが間違った値を印刷しています。我々は前方私たちのテンプレートを宣言するように周りのあなたのコードを移動し(これは常に良い習慣である)場合、あなた」、今

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 

:(I was able to reproduce with VC 19.00.23506

はここでコールトレース(instrumented with some help from C++17)です

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... 

あなたが望む動作を得るでしょう。そのバージョン(demo)からのスタックトレースは次のとおりです。

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(char a, A... args) with 4,5 
Called P(T) with 4 
Called foo(char a) with 5 
Called P(T) with 3 
Called P(T) with 5 
Called P(T) with 48 
関連する問題