2009-03-13 10 views
8

整数値をパラメータとして使用するC++のテンプレートを使用している場合、関数呼び出しでパラメータとして使用された場合とは異なる、整数変数にパラメータとして使用される要件はありますか?C++テンプレートパラメータの要件は何ですか?

これは質問hereのフォローアップです。私は具体的には、関数やテンプレートの "extern const int"として宣言されたWRT変数の違いがある場合に対処したいと思いますか?

いくつかのテンプレートのケースでは、コンパイル時にパラメータ値が必要になることがわかりました。これはいつも真実ですか?実行時に値を使用するように、パラメータ値の特定の用途のみを指定する方法はありますか?

答えて

3

コンパイル時にintの値が常に必要な場合があります。

各テンプレートインスタンシエーションは、コンパイルされたコードの別個の部分(整数テンプレートのパラメータの場合でも)であるため、コンパイル時に整数を使用できる必要があります(変更しないことが保証されている必要があります)。

これは、膨大な数の一意の値を使用するときに、整数テンプレートパラメータを使用しないことをお勧めします。膨大な実行可能ファイルですばやく終了できます。

13

以下は標準からのものです。

14.3.2.1:

非タイプのテンプレート引数、非テンプレートテンプレートパラメータのいずれかでなければならない:

  • 積分または列挙の積分定数式タイプ;または
  • 非タイプのテンプレートパラメータの名前。または
  • ファンクションテンプレートとファンクションテンプレートIDを含み、非スタティッククラスメンバを除き、&と表される外部リンクを持つオブジェクトまたはファンクションのアドレスです。id-expression &はオプションです。配列、または対応するテンプレートパラメータが参照である場合。または
  • 5.3.1で説明したように表現されたメンバーへのポインター。

5.19.1:いくつかの場所で

、C++は、一体または列挙定数に評価式を必要とする:配列境界(8.3.4、5.3.4)のように、ケース式として(9.6)、列挙子初期化子(7.2)、静的メンバー初期化子(9.4.2)、および整数型または列挙型非型テンプレート引数(14.3)として定義されています。

constant-expression: 
      conditional-expression 

整数定数式を含むことができる唯一のリテラル(2.13)、列挙子、constの変数または定数式(8.5)、一体型または列挙の非型テンプレートパラメータで初期化された整数または列挙型の静的データメンバ型、およびサイズの式浮動小数点数(2.13.3)は、整数型または列挙型にキャストされている場合にのみ表示されます。整数型または列挙型への型変換のみが使用できます。特に、sizeof式を除いて、関数、クラスオブジェクト、ポインタ、または参照は使用されず、代入、インクリメント、デクリメント、ファンクションコール、またはカンマ演算子は使用されないものとする。あなたの前のポストに関して

私は一部で本質「のconst変数... がで...を初期化」(と私は初期化が外部カウントとは思わない)と考えています。

4

整数定数式でなければなりません。それは5.19で標準文書で説明しています:

整数定数式のみリテラル(2.13)、列挙子、constの変数または定数式(8.5)で初期化された整数または列挙型の静的データメンバを含むことができる、非型または列挙型のテンプレートパラメータ、およびsizeof式。浮動小数点数(2.13.3)は、整数型または列挙型にキャストされている場合にのみ表示されます。整数型または列挙型への型変換のみが使用できます。

「整数」は「整数」の別の用語ですが、「整数」と同じではありません。例えば、 "char"は整数型/整数型ですが、明らかにint型ではありません。

上記で詳述したようそう具体的に、以下は、それらのいずれかが可能な任意の他のテンプレートパラメータ、もちろん

  • 10 or 10L or anything like that
  • enum { THIS, OR, THAT };
  • int const this_one = 10;
  • sizeof(char)
  • を許可されています整数型thを持つパラメータのテンプレート引数として使用されます。 e対応するタイプ。いくつかのコンバージョンはまだ適用されます。したがって、intを必要とし、charを渡すと、自動的にcharをintに昇格させます。列挙子を提供してintを必要とする場合と同じです。これらのルールによってそのよう

    、あなたが

    extern const int SomeName; 
    

    を持っており、それは整数定数式と定数、それはテンプレート引数として使用することができないことを初期化定義を参照していない場合。もちろん関数の引数として使うことができます。コンパイル時に型の一部ではないので、それらを知る必要はありません。あなたはテンプレートの特殊化に名前を付けた瞬間は、あなたが使用される引数の型の一部となる:が引数としてSomeNameを渡す他の方法があることを

    MyGreatStack<int, 4> // 4 is now part of the type MyGreatStack<int, 4>! 
    

    注意。しかしながら、これらの全ては、整数テンプレートパラメータによって受け入れられることができる。ではない。あなたは一例

    template<const int& V> struct NowItWorks { }; 
    

    のために、参照パラメータによって上記を受け入れることができ、それが上記のSomeNameを受け入れるだろう。ここでは、値ではなく、プログラム全体で一意の特定の場所(変数にはexternリンケージがあるため)が選択されています。

関連する問題