8

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

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

一部のテンプレートのケースでは、コンパイル時にパラメーター値が必要になることがわかります。これは常に真実ですか?おそらくパラメータ値の特定の用途のみに対して、実行時に値が使用されるように指定する方法はありますか?

4

3 に答える 3

13

以下は規格から。

14.3.2.1:

非型、非テンプレートのテンプレート パラメータのテンプレート引数は、次のいずれかになります。

  • 整数型または列挙型の整数定数式。また
  • 非型テンプレート パラメータの名前。また
  • 関数テンプレートと関数テンプレート ID を含むが非静的クラス メンバーを除く、外部リンケージを持つオブジェクトまたは関数のアドレス。対応する template-parameter は参照です。また
  • 5.3.1 で説明されているように表現されたメンバーへのポインター。

5.19.1:

いくつかの場所で、C++ は整数または列挙定数に評価される式を必要とします: 配列境界 (8.3.4、5.3.4)、ケース式 (6.4.2)、ビットフィールド長 (9.6)、列挙子初期化子として(7.2)、静的メンバー初期化子 (9.4.2)、および整数型または列挙型の非型テンプレート引数 (14.3) として。

 constant-expression:
            conditional-expression

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

あなたの以前の投稿に関して、私は「const変数...で初期化された...」の部分の本質を信じています(そして、外部的に初期化されたとは思いません)。

于 2009-03-13T18:12:58.277 に答える
4

整数定数式でなければなりません。これは、次の標準ドキュメントで説明されています5.19

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

「整数」は「整数」の別の用語ですが、「int」と同じではないことに注意してください。たとえば、「char」には整数/整数型がありますが、明らかに int 型ではありません。したがって、具体的には、次のことが許可されます

  • 10 or 10L or anything like that
  • enum { THIS, OR, THAT };
  • int const this_one = 10;
  • sizeof(char)
  • もちろん、上記で詳述した他のテンプレート パラメータ

これらのいずれも、対応する型の整数型を持つパラメーターのテンプレート引数として使用できます。ただし、一部の変換は引き続き適用されます。したがって、int が必要な場合に char を渡すと、自動的に char が int に昇格されます。列挙子を提供し、int が必要な場合も同様です。

したがって、それらのルールによって、もしあなたが持っているなら

extern const int SomeName;

また、その定数を整数定数式で初期化する定義が表示されないため、テンプレート引数として使用できません。もちろん、関数の引数として使用することもできます。これらは型の一部ではないため、コンパイル時に知る必要はありません。テンプレートの特殊化に名前を付けると、使用した引数が型の一部になります。

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

引数として渡す方法他にもあることに注意してください。SomeNameただし、これらすべてを整数テンプレート パラメータで受け入れることはできません。たとえば、参照パラメーターによって上記を受け入れることができます

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

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

于 2009-03-13T18:14:58.753 に答える
3

コンパイル時に int の値が必要になることは常にあります。

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

これが、多数の一意の値を使用する場合に整数のテンプレート パラメータを使用しないことをお勧めする理由でもあります。すぐに巨大な実行可能ファイルになってしまう可能性があります。

于 2009-03-13T17:30:43.667 に答える