2017-10-19 13 views
3

文字列リテラルのテンプレート特殊化を追加しようとしている間、VS 2017コンパイラとVS 2010コンパイラの動作の違いに気付きましたVS 2017から)(Visual-)文字列リテラルのC++テンプレート型推論 - VS 2010 VS VS 2017

これは、問題のコードです:VS 2017のデフォルトのコンパイラを使用して

#include <iostream> 

template <typename T> 
struct foo 
{ 
    static const int a = -1; 
}; 

template <size_t n> 
struct foo<char[n]> 
{ 
    static const int a = 0; 
}; 

template <size_t n> 
struct foo<const char[n]> 
{ 
    static const int a = 1; 
}; 

template <typename T> 
int bar(const T& x) 
{ 
#pragma message (__FUNCSIG__) 
    return foo<T>::a; 
} 

int main() 
{ 
    std::cout << _MSC_VER << '\n'; 
    std::cout << bar("a") << '\n'; 
} 

が実行:

int __cdecl bar<char[2]>(const char (&)[2]) 
1911 
0 
VS 2010のコンパイラを使用して

し、実行:

int __cdecl bar<const char[2]>(const char (&)[2]) 
1600 
1 

あなたが見ることができるように、Tは、新しいもののために、古いコンパイラのconst char[2]が、char[2]と推定されます。何が変わったの?これはVisual Studioのバグ修正/バグですか?またはC++ 11/C++ 14で正しい動作が変更されていますか?

tio.run(gccとclangの両方)で試してみると、VS 2017が正しいと思われますが、これは正しいですか?

+0

FWIWでは、C++の文字列リテラルは常に 'const char [N]'でしたが、VSとCの互換性のために 'char [N]'があれば理解できます。 – chris

答えて

1

これは単純なタイプのマッチングです。

あなたの機能はconst T&です。整数を渡すとTintと推測されるので、署名はconst int&です。 const intとしてそれを控除することは冗長にすぎません。

あなたが見ることができるように、あなたのパラメータはすでにconst内にありますので、それは離れています。

MSVC 2010のバグは、以前のバージョンのVisual Studioではテンプレートの実装がかなり低かったため、修正されています。

+0

清算してくれてありがとう - 私は何かを見逃しているかどうか疑問に思っていましたが、あなたの説明を読んで質問がかなり馬鹿に見えるようになります – Mathe172

+0

@ Mathe172あなたの質問は正当なものだったので、 –