2011-09-20 11 views
8

C++がテンプレートをどのようにインスタンス化するのか混乱します。私は、コードの一部を持っている:ここではC++でのテンプレートのインスタンス化

template <class T, int arraySize> 
void test1(T (&array)[arraySize]) 
{ 
    cout << typeid(T).name() << endl; 
} 

template<class T> 
void test2(T &array) 
{ 
    cout << typeid(T).name() << endl; 
} 

int main() 
{ 
    int abc[5]; 
    test1(abc); 
    test2(abc); 
    return 0; 
} 

は私の質問です:
1.配列ABCのサイズは(パラメータARRAYSIZEを)TEST1に渡されない方法は?
2. C++コンパイラは、2つのテンプレートのTの種類をどのようにして決定しますか?テンプレートパラメータは、コンパイル時に解決されているので

+1

示して?第二のものは全く意味をなさない。あなたは 'test2 'という関数を持っていて、それを配列のように索引付けしていますか? – Shahbaz

答えて

4

test1では、コンパイラは、T [arraySize]がそのフォームであるテンプレートを作成します。 test1(abc)を呼び出すと、テンプレートマッチャーが自動的に一致するint [5]型の入力引数を提供しています。あなたは

int n=10; 
int *abc = new int[n]; 
test1(abc); 
test1<int,n>(abc); 

を書くとしたら

しかし、その後、コンパイルは失敗し、コンパイラは、TEST1(ABC)関数呼び出しまたはtest1の< int型に一致するテンプレートを持っていないと主張するだろう、N>( abc)関数呼び出し。

これは、abcのサイズが動的に割り当てられるため、abcの型が異なる型のポインタであり、したがって上記の2つの呼び出しにテンプレートを一致させることができないためです。

次のコードは、あなたが `test1の (ABC)`のようなものを意味し、いくつかの種類

#include <iostream> 
using namespace std; 

template <class T> void printName() {cout<<typeid(T).name()<<endl;} 

int main() 
{  
    printName<int[2]>(); //type = A2_i 
    printName<int*>();  //type = Pi 

    getchar(); 
    return 0; 
} 
+1

さらに、 'abc [n]'はコンパイルされません。なぜなら、C++は動的サイズの配列(私が知る限り、C++ 11でさえも)をサポートしていないからです。あなたはC99の背景を持っていると思いますか? –

+0

これはapple llvm compiler 3.0の下でうまくコンパイルされました。答えを更新しました。それを指摘してくれてありがとう。 – twerdster

7
  1. は、通常の意味で渡すパラメータはありません。
  2. arraySizeTの両方が、arrayパラメータのタイプから推測されます。 int[5]を渡すので、5arraySizeTは、それぞれコンパイル時にとなります。

たとえば、int* abc = new int[5];を宣言した場合、コンパイラはtest1(abc)を呼び出しようとした時点でバーフします。基本的なタイプミスマッチとは別に、int*は配列のサイズを推測するのに十分な情報を持っていません。

5

テンプレート引数の控除と呼ばれます。

呼び出しサイトでabcタイプは次のとおりです。int5:2つの情報を組み合わせていint(&)[5]。関数テンプレートはT(&)[N]の引数を受け取りますが、call-siteの引数はint(&)[5]なので、コンパイラはTintであり、N5であると推測します。

これらを読む:

0

を私はまた、ナワズが言うに追加したい:理論はtype inferenceです。

関連する問題