2017-11-12 4 views
2

で非型引数と打ち鳴らす++異なる振る舞い私は(C++14に同上と、私はC++ 17には、仮定)14.5.5/8 of the C++11 standardの意味と意義を理解しようとg ++および構造体/クラス専門

タイプ特殊な非型引数に対応するテンプレートパラメータの値は、特殊化のパラメータに依存してはならない。

そして、いつものようにg ++とclang ++の間で誰が正しいのかを理解する。

標準表示次の例

template <class T, T t> struct C {}; 
template <class T> struct C<T, 1>; // error 

両方G ++と打ち鳴らす++エラーを与えます。

これまでのところ、とても良いです。

のタイプ

template <typename, typename T, T> 
struct foo { }; 

template <typename T> 
struct foo<T, int, 1> { }; // compile 

template <typename T> 
struct foo<T, T, 1> { }; // error 

両方G ++と打ち鳴らす++最初の部分的な特殊化をコンパイル(1のタイプ、intは、専門のパラメータではない)でエラーを与えるの追加の例を少し複雑にしましょう2番目のタイプ(1のタイプはT、特殊化のパラメータです)

これまでのところ、とても良いです。

のは、は(++それはグラムでエラーなしでコンパイルされていますテンプレートパラメータ

template <typename> 
struct bar 
{ using type = int; }; 

と、次のプログラム

template <typename> 
struct bar { using type = int; }; 

template <typename, typename T, T> 
struct foo { }; 

template <typename T> 
struct foo<T, typename bar<T>::type, 1> { }; 

int main() 
{ } 

から依存しないことを内部型とテンプレートの構造体barをご紹介しましょう4.9.3,5.5.0,7.2.0、ヘッド8.0.0、C++ 11、C++ 14、および可能であればC++ 17)、clang ++(3.9.1、4.0、 1、5.0.0、ヘッド6.0.0、C++ 11、C++ 14、C++ 17)エラー

prog.cc:11:38: error: non-type template argument specializes a template parameter with dependent type 'T' 
struct foo<T, typename bar<T>::type, 1> { }; 
            ^
prog.cc:7:34: note: template parameter is declared here 
template <typename, typename T, T> 
           ~^ 

通常通り:誰が正しいですか? Tに依存1を検討

打ち鳴らすは++、(typename bar<T>::typeintとして固定されている場合)、またはg ++は、それは、この依存関係を緩和しないのですか?完全のために

私はbarを変更することが

template <typename T> 
struct bar { using type = T; }; 

はそう T、何も変化に bar<T>::type依存を作り、次のようにすることを言っている:G ++エラーなしでコンパイルし、打ち鳴らす++同じエラーを与えます。

答えて

2

コンパイラの観点から見てください。専門のために

template <class T, T t> struct C {}; 
template <class T> struct C<T, 1>; // error 

Tが実際に1の値を持つことができ、そしてその専門が無効な場合、コンパイラは知りません。 typeintが常にあることを言っている

template <typename T> 
struct foo<T, typename bar<T>::type, 1> { }; 

については

?あなたはそれが明らかであると思うかもしれないが、typestd::stringあるように私は1つの特定のTためbarの特殊化を導入する可能性:

template<> 
struct bar<const volatile int> { using type = std::string }; 

基本的には、あなたの文の「typename bar<T>::typeintとして固定されている」が間違っていますそれは固定されていません。

今何ですか?ここでの標準は、最初の例の場合と同じことですが、特殊化は正しくありません。なぜなら、型パラメータが正しく指定されているため、別の(テンプレート化された)特殊化タイプ、つまりTに依存します。不明です。その点では、clangは正しいですし、gccは間違っています。

関連する問題