2012-02-08 14 views
13

Iがパラメータとして、タイプを指定するために使用されている角括弧に使用しています:引数値の山括弧とは何ですか?それは何のために使われますか?

vector<int> vecOfInts ; 

しかし​​では、このようなコードがある:

document.Parse<0>(json) ; 

document.Parseメソッドのシグネチャは次のとおりです。

template <unsigned parseFlags> 
GenericDocument& Parse(const Ch* str) { 
    RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); 
    GenericStringStream<Encoding> s(str); 
    return ParseStream<parseFlags>(s); 
} 

を渡すことができませんでしたサイドアングルブラケット - タイプアットネームだけのために斜め括弧を使用しました。

ここでコードは何ですか、なぜ彼はを山括弧で通していますか?

これは良い考えですか?いつ?

+0

可能な複製[正規パラメータの代わりに非型テンプレートパラメータを使用する理由?](http://stackoverflow.com/questions/7395700/reason-for-using-non-type-template-parameter-instead- of-regular-parameter) –

+2

"non-type template parameter"を参照してください。 –

答えて

18

ここでは2つの異なる要因が考えられます。

まず、タイプ以外のものよりもパラメータ化されたテンプレートを定義することができます。

template <typename T, size_t N> struct Array { 
    T arr[N]; 
}; 

我々はvector<int>vector<double>は、異なるタイプであることを知っている

Array<int, 137> myArray; 

のようにこれを使用することができます:たとえば、ここでは簡単な配列型です。しかし今、我々はまた、Array<int,137>Array<int,136>が異なるタイプであることを指摘しなければならない。

第2に、テンプレートを使用する場合、コンパイラはすべてのテンプレート引数の値を把握できる必要があります。テンプレートクラスを使用している場合、これは通常、すべてのテンプレート引数を指定する理由です。たとえば、vector xとは言っていませんが、代わりにvector<double> xなどと言ってください。テンプレート関数を使用する場合、コンパイラはほとんどの場合引数を把握できます。例えば、std::sortを使用するように、あなただけの何か

std::sort(v.begin(), v.end()); 

などを言うしかし、あなたはまた、より明確であることを

std::sort<vector<int>::iterator>(v.begin(), v.end()); 

を書くことができます。しかし、時には、すべての引数が分かるわけではないテンプレート関数があります。 parseFlagsテンプレートパラメータは、関数の引数だけから推定することができないこと

template <unsigned parseFlags> 
GenericDocument& Parse(const Ch* str) { 
    RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); 
    GenericStringStream<Encoding> s(str); 
    return ParseStream<parseFlags>(s); 
} 

のお知らせ:あなたの例では、我々はこれを持っています。その結果、関数を呼び出すにはテンプレートパラメータを指定する必要があります。そうしないと、コンパイラはそれを理解できません。あなたがここに

Parse<0>(myString); 

のようなものを書きたい理由です、0は(コンパイル時に解決)テンプレート引数で、myStringは(実行時に解決)実引数です。

実際には、型推論のビットと明示的な型パラメータのビットを組み合わせたメソッドを持つことができます。たとえば、Boostには、文字列型との変換を行うことができる関数lexical_castがあります。文字列型の非文字列型から変換する関数のシグネチャを使用すると、lexical_castを呼び出す場合、コンパイラはSourceが何であるかを把握することができますが、それはいくつかのヒントなしでTargetを推測することはできません、ここで

template <typename Target, typename Source> 
    Target lexical_cast(const Source& arg); 

です。 lexical_castを使用するには、そのため、あなたはより一般的

std::string myString = boost::lexical_cast<std::string>(toConvertToString); 

のようなものを書きたい、コンパイラは、テンプレートの引数(オプション0)のいくつかの番号を指定する必要があり、それは残りの部分を推測しようとすると述べています。それができれば、素晴らしい!そうでない場合は、コンパイル時エラーです。これはあなたのために動作し、ここで

DoSomething<intArg>(otherArg); 

:あなたが欲しい場合は、これを使用して、あなたはこの関数を呼び出すには

template <int IntArgument, typename TypeArgment> 
    void DoSomething(const TypeArgument& t) { 
     /* ... */ 
} 

のような関数を書くことができ、あなたはこのようにそれを呼び出す必要があるだろうコンパイラにIntArgumentが何であるかをコンパイラに明示的に伝える必要がありますが、コンパイラはを引数の型からDoSomethingに推定できます。

希望すると便利です。

関連する問題