11

テンプレートパラメータとして整数値を取り、それらに対して算術演算を実行できるので、boost :: mpl :: int _ <>およびその他の整数定数の背後にある動機は何ですか?この動機はC++11にも当てはまりますか?

4

2 に答える 2

13

整数値をテンプレートパラメータとして使用できますが、単一のテンプレートで型と非型の両方のテンプレートパラメータを使用することはできません。簡単に言うと、型以外のテンプレートパラメータ型として扱うことで、 MPL内の無数の物でそれらを使用できるようになります。

たとえば、型を処理findし、シーケンス内で等しい型を探すメタ関数について考えてみます。タイプ以外のテンプレートパラメータで使用する場合は、新しいアルゴリズム「オーバーロード」を再実装する必要があります。このためには、積分値のタイプfind_cを手動で指定する必要があります。ここで、他の言語と同じように整数型を混合して動作させたい場合、または型を混合したい場合を想像してみてください。「オーバーロード」が爆発的に増加します。あらゆる場所で各非型パラメーターの型を指定します。

この動機は、C++11でも引き続き適用されます。

この動機は、非型テンプレートパラメータから型テンプレートパラメータへの変換を許可する新しいルールがない限り、 C++yおよびその他のバージョンにも適用されます。たとえば、を使用し、テンプレートがタイプを要求するたびに、代わりにそれをインスタンス化します。5std::integral_constant< int, 5 >

于 2013-01-17T22:43:30.810 に答える
13

tldr; 値を型としてエンコードすると、単純な値よりもはるかに多くの場所で使用できるようになります。型をオーバーロードすることはできますが、値をオーバーロードすることはできません。

K-Balloの答えは素晴らしいです。

しかし、私が関連すると思う他の何かがあります。積分定数型は、テンプレートパラメータとして役立つだけでなく、関数の引数や関数の戻り型としても役立ちます(私の例では、C ++ 11型を使用していますが、同じ引数が、それらより前のBoost型にも当てはまります)。

template<typename R, typename... Args>
  std::integral_constant<std::size_t, sizeof...(Args)> 
  arity(R (*)(Args...))
  { return {}; }

この関数は関数ポインタを受け取り、関数が取る引数の数を示す型を返します。関数が登場する前はconstexpr、定数式で関数を呼び出す方法がなかったので、「この関数型はいくつの引数を取るのか」などの質問をします。タイプを返し、そこから整数値を抽出する必要があります。

constexpr言語を使用している場合でも(つまり、上記の関数return sizeof...(Args);はコンパイル時に使用可能であり、その整数値はコンパイル時に使用可能です)、タグのディスパッチなど、整数定数型の適切な使用法があります。

template<typename T>
  void frobnicate(T&& t)
  {
    frob_impl(std::forward<T>(t), std::is_copy_constructible<T>{});
  }

この関数は、2番目の引数として渡されfrob_implた型に基づいてオーバーロードできます。integer_constant<bool, b>

template<typename T>
  void frob_impl(T&& t, std::true_type)
  {
    // do something
  }

template<typename T>
  void frob_impl(T&& t, std::false_type)
  {
    // do something else
  }

ブール値をテンプレートパラメータにすることで、同様のことを試すことができます。

frob_impl<std::is_copy_constructible<T>::value>(std::forward<T>(t));

ただし、関数テンプレートを部分的に特殊化することはできないためfrob_impl<true, T>frob_impl<false, T>別のことを作成して実行することはできません。ブール定数のタイプをオーバーロードすると、「コピー構築可能」特性のに基づいてさまざまなことを簡単に実行できます。これは、C++11でも非常に役立ちます。

定数が役立つもう1つの場所は、SFINAEを使用してトレイトを実装することです。intC ++ 03では、従来のアプローチは、サイズの異なる2つの型(たとえば、 2つのsを含む構造体と構造体)を返すオーバーロードされた関数を使用しint、「値」をでテストすることsizeofでした。C ++ 11では、関数が返される可能性がtrue_typeあり、false_typeこれははるかに表現力があります。たとえば、「このタイプにはfoo「?」というメンバーがありますか?」をテストするトレイトがあります。正の結果を示す関数を返し、true_type負の結果を示す関数を返すfalse_typeことができますが、それよりも明確なことは何でしょうか。

標準ライブラリの実装者として、私はとを頻繁に使用します。これは、コンパイル時の「質問」の多くが正誤問題であるためですが、2つ以上の異なる結果が得られる可能性のあるものをテストする場合は、他の専門分野を使用します。。true_typefalse_typeintegral_constant

于 2013-01-18T00:21:58.533 に答える