C ++メタプログラミングですべてのテンプレートを使用していますか?


8

私はメタプログラミングが一般的であり、特にそれがC ++で何であるかを理解しようとしています。c ++メタプログラミングを検索すると、テンプレートメタプログラミング(TMP)のチュートリアルは表示されますが、テンプレートの特定の使用法またはテンプレートのすべての使用法のみが分類されているかどうかの説明はありません。

私の質問は、C ++でのテンプレートのすべての使用がメタプログラミングとして分類されるかどうかです。それがなぜなのか、そうでないのかについての説明も役に立ちます。ありがとうございました。


1
CLマクロと比較して、Greenspunの10番目のルールを確認してください。 en.wikipedia.org/wiki/Greenspun%27s_tenth_rule
スターク

1
TMPはメタプログラミングの唯一の方法ではありません。マクロ(ええと)とconstexpr関数でメタプログラミングを行うこともできます。ConstexprはTMPよりも実装が簡単です。
zett42

1
@ zett42コンパイル時にコードを単に実行するだけが「メタプログラミング」と見なされるべきかどうかはわかりません。それはプログラミングではなく、コンピューティングだからです。実行時からコンパイル時に実行をシフトするだけです。C ++でのメタプログラミングは、コード(テンプレート、マクロ)を生成するため、それとは異なります。
Johannes Schaub-litb

回答:


2

私の質問は、C ++でのテンプレートのすべての使用がメタプログラミングとして分類されるかどうかです。

番号。

C ++では、テンプレートのすべての使用法がメタプログラミングであるとは限りません。

明らかにそれは定義の問題ですが、C ++では「メタプログラミング」は「コンパイル時の計算」と同義です。

したがって、テンプレートを使用してメタプログラミング(具体的にはテンプレートメタプログラミング)を行いますが、テンプレートのすべての使用がメタプログラミングであるとは限りません。

単純な反例

template <typename K, typename V>
void printKeyVal (K const & k, V const & v)
 { std::cout << k << ": " << v << std::endl; }

上記printKeyVal()は、いくつかの一般的な値を標準出力(つまり、コンパイル時ではなく実行時)に出力するテンプレート関数です。

コンパイル時に実行できないため、「テンプレート」ですが、「メタプログラミング」ではありません。

より一般的にstd::vectorは、メモリ割り当てを使用するテンプレートクラスです。また、メモリ割り当て(C ++ 17まで。将来的には異なる可能性があります)は、コンパイル時のコードでは使用できません。

したがって、std::vector(それとは逆にstd::array、サイズが固定されていて、メモリ割り当てを使用していません)は、std::vectorメタプログラミングに使用できない(使用がオブジェクトのインスタンス化を伴う場合)テンプレート機能です。


それでも、テンプレートに依存する関数には、少なくともいくつかのメタプログラミングが必要です。あなたの例でprintKeyValは、テンプレートされた引数に従ってコンパイル時に定義されます
SomeWittyUsername

プログラムするときは、コードを記述します。あなたは物事を「計算」しません。したがって、「メタプログラミング」を「コードを書くためのコードを書く」と定義します。そして、これがまさにすべてのテンプレートの目的です。テンプレートのメタプログラミングは「コンパイル時の計算」によく使用されることは承知していますが、個人的には別の用語を使用します(私は過去にそうしたことがないので、申し訳ありません)。
ヨハネスシャウブ-litb

@ JohannesSchaub-litb-言語と定義の問題(そして私は英語がよくわからないという追加のハンディキャップがあります)であり、すべてのテンプレートを含む「メタプログラミング」の定義が可能であり、おそらくまた可能であることに同意します合理的。私が言うことは、C ++コミュニティでは、「メタプログラミング」という用語は、交差するがテンプレートのすべての使用を含むわけではない、異なる意味で使用されているということです。多分私は間違っている...興味深い投票かもしれない。
max66

テンプレートのコードがタイプごとに1:1で複製されていない場合にのみ、「メタプログラミング」と呼ばれる可能性があります。1:1で複製されている場合、テンプレートコードは完全にパッシブであり、すべての「メタプログラミング」はコンパイラによって行われるためです。 。特殊化、static-if、overload-dispatchingなどがある場合、何を生成するかを決定するのはコード自体です。これはDのスタンスのようです:tour.dlang.org/tour/en/gems/template-meta-programming
Johannes Schaub-litb

@SomeWittyUsername-あなたは「メタプログラミング」の定義を使用しているようですが、これは完全に合法であり、おそらく合理的でもあり、C ++コミュニティが実際に使用しているものとは異なります:乱暴に言えば、「メタプログラミング==コンパイル時実行」。多分私は間違っていて、コミュニティは主にすべてのテンプレートの使用を含む定義を使用しています...興味深い投票かもしれません。
max66

1

C ++のTMPとは何ですか?

C ++のテンプレートメタプログラミング(TMP)は、C ++テンプレートを使用してコンパイル時に任意のアルゴリズムを表現および実行するための手法です。これは通常、条件付きブランチをエミュレートするテンプレート特殊化とループをエミュレートする再帰的なテンプレート定義を使用することで有効になります。最もよく知られている例は、コンパイル時の階乗計算です。

template <unsigned int n>
struct factorial {
    // recursive definition to emulate a loop or a regular recursion
    enum { value = n * factorial<n - 1>::value };
};

// specialization that describes "break" condition for the recursion
template <>
struct factorial<0> { 
    enum { value = 1 };
};

前述の手法の両方を使用します。

しかし、はるかに一般的なのは、実際の数値計算ではなく、型の検出と変換にTMPを使用することです。たとえば、標準std::is_pointerユーティリティ(source)です。

// generic definition that emulates "false" conditional branch
template<class T>
struct is_pointer_helper : std::false_type {};

// a specialization that emulates "true" conditional branch
template<class T>
struct is_pointer_helper<T*> : std::true_type {};

template<class T>
struct is_pointer : is_pointer_helper< typename std::remove_cv<T>::type > {};

標準のtype_traitsヘッダーで提供されるユーティリティのほとんどは、TMP技術を使用して実装されています。

TMPアルゴリズムは型定義を用いて表現されていることを考えると、それの価値TMPは、の形式であることを言及する宣言型プログラミング(計算ロジックは、明示的な制御フロー・ステートメントを使用せずに発現されるifelsefor...など)。

C ++テンプレートのすべての使用はメタプログラミングですか?

短い答えは次のとおりです。いいえ。テンプレートがコンパイル時アルゴリズムの表現に使用されていない場合、それはメタプログラミングではなく、一般的なプログラミングです。

C ++でテンプレートを導入するための第一の目標は、同じアルゴリズム(再利用できるようにすることですジェネリックプログラミング、有効にしたfindcopysort、など)とデータ構造を(vectorlistmapUSER-を含む任意のタイプのために、等...)、特定の要件を満たす定義済みのもの。

実際、C ++のTMPは偶然発見されたものであり、テンプレートの使用目的ではありませんでした。


要約すると、C ++でのテンプレートメタプログラミングは、コンパイル時アルゴリズムを表現するためのテンプレートの使用です。C++テンプレートの他のほとんど(すべて?)の使用は、一般的なプログラミングの形式です。


0

私はメタプログラミングが一般的であり、特にC ++で何であるかを理解しようとしています

メタプログラミングで理解できることはまだ一般的に言っていないため、答えに共通の出発点はありません。

ウィキペディアの定義はこれで十分だと思います。

メタプログラミングとは、コンピュータプログラムが他のプログラムをデータとして扱う機能を持つプログラミング手法です。

...計算を実行時からコンパイル時に移動し、コンパイル時の計算を使用してコードを生成するために使用できます...

C ++では通常、自己変更コードを許可していないため、無視します。また、コンパイル時(またはほぼ間違いなく直前)のテキスト置換はプログラムのセマンティクスの操作と同じではないため、プリプロセッサーをカウントしないことも選択しています。

私の質問は、C ++でのテンプレートのすべての使用がメタプログラミングとして分類されるかどうかです

いいえそうではありません。

参考までに、

#define MAX(a,b) ((a) > (b) ? (a) : (b))

これは、maxテンプレートを使用せずに一般的な(型にとらわれない)関数を書く方法です。プリプロセッサをメタプログラミングとして数えないことはすでに述べましたが、いずれにしても、使用されるたびに常に同じコードを生成します。

後の変換フェーズで、そのコードの解析、型、およびa>bコンパイラに定義されているかどうかの心配を委任するだけです。コンパイル時動作するものはありません...に応じて異なる結果コードを生成します。コンパイル時には何も計算されません。

これで、テンプレートのバージョンを比較できます。

template <typename T>
T max(T a, T b) { return a > b ? a : b; }

これは単にテキストによる置換を実行するだけではありませ。インスタンス化のプロセスはより複雑で、名前のルックアップルールとオーバーロードが考慮される場合があります。また、ある意味では、異なるインスタンス化はテキスト的に同等ではない場合があります(例:使用するものbool ::operator< (T,T)と使用するbool T::operator<(T const&)もの)。

ただし、各インスタンス化の意味は同じで(operator<異なるタイプの互換性のある定義を想定している場合など)、タイプや名前などを解決するコンパイラーの通常の(機械的な)プロセスを除いて、コンパイル時に何も計算されませんでした。

余談として、それはあなたのプログラムが含まれていることを十分に間違いはありません何をすべきか、それを伝えるために、コンパイラのための命令をそれが何だから、すべてのプログラムがあります。

今、次のような限界的なケースがあります

template <unsigned N>
struct factorial() { enum { value = N * factorial<N-1>::value }; };

これ計算をコンパイル時間に移動します(この場合、ターミナルケースを書くのに煩わされないので、終了しない計算になります)が、おそらくメタプログラミングではありませ

ウィキペディアの定義では、計算をコンパイル時に移動することを述べていましたが、これは単なる値の計算にすぎません。コードの構造やセマンティクスについてコンパイル時に決定を下すものではありません。


-1

テンプレートを使用してC ++関数を作成するときは、関数の呼び出しが発生したときにコンパイラーが何をすべきかを指示する「命令」を作成しています。この意味では、直接コードを記述しているわけではないため、これをメタプログラミングと呼びます。

つまり、テンプレートを含むすべてのC ++コードはメタプログラミングと見なされます

テンプレートの関数またはクラスを定義する部分のみがメタプログラミングであることに注意してください。通常の関数とクラスは通常のC ++として分類されます。


1
Bashで「cp a.txt b.txt」と入力すると、本格的なプログラミング環境を使用していますが、これはプログラミングではありません。同様に、私が使用する場合std::vector、コンパイラーにプログラムを生成するように指示します(そのため、実際にはメタです)が、命令自体はほとんどプログラムではありません。ほとんどの人はマクロの「メタプログラミング」の使用を考えていません。
n。「代名詞」m。

1
あなたの答えは単に間違っています!MTPの意味を基本的に理解するには、このスレッドで提供されている他の回答をお読みください。
クラウス

1
テンプレートなしで C ++を書くときはいつでも、コンパイラーのための命令を書いています。つまり、テンプレートがコンパイラに何をすべきかを伝えるという事実は、プログラミングとメタプログラミングを区別するのに十分ではありません
役に立たない

1
@ JohannesSchaub-litb C ++のコンテキストでは、「メタプログラミング」という用語には、その一般的な意味とは異なる特定の意味があります。IIRCは当初、A.Alexandrescuが著書 『Modern C ++ Design』で作成した発見されたC ++機能を参照していました。C ++でのテンプレートの従来の使用法は、メタプログラミングではありません(C ++以外の用語のメタプログラミングを使用しない限り)。
YSC

1
OPの質問から:「私はメタプログラミングが一般的であり、それが特にC ++で何であるかを理解しようとしています」。だから私はあなたの角度は問題なく、素晴らしい答えになると思います。しかし、これはそうではありません。-1
YSC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.