2013-01-17 5 views
10

テンプレートパラメータとして積分値を取って算術演算を実行できるので、boost :: mpl :: int_ <>と他の整数定数の背後にある動機は何ですか?このモチベーションはまだC++ 11にも当てはまりますか?Boost MPLに整数定数があるのはなぜですか?

+6

Boost MPLの主著者の著書「C++ Template Metaprogramming」を読んで、これらのすべての背後にある動機について説明します。これはC++ 11でのみ有効ではなく、[std :: integral_constant](http://en.cppreference.com/w/cpp/types/integral_constant)でC++ 11で標準化されています。 –

答えて

12

あなたはテンプレートパラメータとしての整数値を取ることができますが、単一のテンプレートで種類非型テンプレートパラメータの両方を取ることができません。長い話は短く、型テンプレートパラメータ以外のテンプレートパラメータタイプとすると、MPL の無数のものに使用できます。例えば

、シーケンス内の同じタイプの種類とルックスで動作するメタ関数findを検討してください。 型テンプレートパラメータ以外のテンプレートパラメータを使用する場合は、新しいアルゴリズムのオーバーロードを再実装する必要があります。find_cタイプを手動で指定する必要があります。今度は、それが言語の残りの部分と同じように混在したタイプで動作したいと思っているか、またはタイプ以外のタイプを混在させたい場合、あなたは爆発的な「過負荷どこでも非型パラメータの型を指定する必要があるので、使用するのは難しいです。

この動機はまだC++ 11に適用されます。

この動機はまだC++に適用されますYと他のバージョン、我々は非型テンプレートパラメータからタイプテンプレートパラメータに変換することができますいくつかの新しいルールを持っていない限り。たとえば、5を使用し、テンプレート要求でタイプを使用するたびにstd::integral_constant< int, 5 >でインスタンス化します。

+2

C++ y?私はそれがC++ 1yだと思った? –

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>{}); 
    } 

このfrob_impl関数は、2番目の引数として渡された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では非常に便利です。

SFINAEを使用して形質を実装するために、定数が便利な別の場所があります。 C++ 03では、従来のアプローチでは、サイズが異なる2つのタイプ(例えば、intと2つのintを含む構造体)を返すオーバーロードされた関数を用意し、 "値"をsizeofでテストしました。 C++ 11では、関数はより表現力豊かなtrue_typefalse_typeを返すことができます。 「このタイプにはfooというメンバーがありますか?正の結果を示す関数をtrue_typeとし、負の結果を返す関数をfalse_typeと返すようにすることができます。

コンパイル時「質問」の多くは、真/偽の答えを持っているので、私は2以上のものを持つことができる何かをテストしたい場合、標準ライブラリの実装者として、私は、true_typefalse_type非常に頻繁に利用します異なる結果integral_constantの他のスペシャライゼーションを使用します。

+0

'foo'と' bar'の何が問題なのですか? :P –

+0

他のメタシンセティック変数にも愛が必要です! –

関連する問題