深く浅く分析するC++trits技術
前言
tritsは、特性抽出技術とも言われています。簡単に言えば、「伝達されたオブジェクト」に対応する返却タイプを抽出して、同じインターフェースに対応する機能を実現させることです。STLのアルゴリズムとコンテナは分離されているので、両者はローズマリーでリンクされています。アルゴリズムの実現は、自分が何を伝えられているかを知らない。抽出器は、インターフェースと実装の間にパッケージを追加することに相当し、いくつかの詳細を隠し、適切な方法の呼び出しを支援する。これはいくつかの技術(例えば、偏特化)が必要である。最後に小さな例が付いています。特性抽出をよりよく理解できるはずです。
以下の大部分は『STLソース解析』に由来しています。原書を読むと、より多くの詳細が分かります。
Traitsプログラミング技法
問題を少しずつ投げて、少しずつ深く入りましょう。
1.まず、アルゴリズムの中でローズマリーを使うと、その該当するパターンが使われる可能性が高いです。アルゴリズムで変数を宣言する必要があると仮定しますが、「サブコマンダーの指す対象の型别」を型别としてどうすればいいですか?
解決方法は、function templateを利用したパラメータ導出メカニズムです。
ローズマリー対応の型は「ディエゼルの指す対象の型别」だけではありません。経験によると、最も一般的な対応型は5種類ありますが、いずれも上記のtemplateパラメータ導出機構を利用して取得することができます。
関数の「templateパラメータ導出機構」で導出されたのはパラメータだけで、関数の戻り値の種類は導出できません。関数の回送値を導き出す必要があったら、どうすることもできません。
2.インサイダー宣言はいいアイデアのようです。直接に入手できます。
この時は特化が必要です。
3.偏った特化とは特化に加えて制限を加えることであるが、特化したtemplateである。
以下に「STLソース解析」の画像を添付します。
トラストにもっと多くのことをさせます。
ローズマリーはよくある5種類のタイプがあります。value_タイプライタータイプライタータイプライターtypeはtritsと対応する偏向特化から抽出しやすいです。でも、iteratorcategoryは普通は5つもあります。これによって、大きな規模のコード作成工程が発生します。
例えば、func_を実現しました。II,func_BI,func_RAIは、それぞれ、サブエージェントタイプを表しています。Input Iterator、Bidirectional Iterator、Random Access Iteratorの対応が実現されます。
今、お客様がフルnc()を呼び出す時、判断が必要かもしれません。
この関数機構を再負荷するとこの目標が達成できる。
ここまでは、各型式の具体的な積載が完了しましたが、統一されたインターフェースが必要です。この時、トレーツは出場できます。
だから、tritsは一方で、異なる入力クラスに直面する時、適切なリターンパターンを見つけることができます。一方、パターン別対応が異なる実装関数がある場合は、パターンを抽出して分岐する役割を果たすことができる。
まず、func関数があると仮定して、カスタマイズされたクラスやオリジナルのポインタをパラメータとして受け入れて、自動的に出力して何を使っていますか?
まずtritsに従って、uの戻りパターンを抽出し、対応する構造関数return_を呼び出します。type()は、各重載バージョン_u u ufuncの重負荷フラグは、異なる実際の関数を区別します。
まず、インタフェースコードの作成を見ます。
付属する
以下は完全コードです。
特性抽出に時間がかかりましたが、プログラムが飛び出した瞬間はとても楽しかったです。
まず、侯捷先生に感謝します。先生の本はこんなにはっきりと説明しています。
これを見たら画像のフーリエ変換が見られます。あはは。
以上はC++trits技術についての簡単な話です。C+trits技術に関する資料は他の関連記事に注目してください。
tritsは、特性抽出技術とも言われています。簡単に言えば、「伝達されたオブジェクト」に対応する返却タイプを抽出して、同じインターフェースに対応する機能を実現させることです。STLのアルゴリズムとコンテナは分離されているので、両者はローズマリーでリンクされています。アルゴリズムの実現は、自分が何を伝えられているかを知らない。抽出器は、インターフェースと実装の間にパッケージを追加することに相当し、いくつかの詳細を隠し、適切な方法の呼び出しを支援する。これはいくつかの技術(例えば、偏特化)が必要である。最後に小さな例が付いています。特性抽出をよりよく理解できるはずです。
以下の大部分は『STLソース解析』に由来しています。原書を読むと、より多くの詳細が分かります。
Traitsプログラミング技法
問題を少しずつ投げて、少しずつ深く入りましょう。
1.まず、アルゴリズムの中でローズマリーを使うと、その該当するパターンが使われる可能性が高いです。アルゴリズムで変数を宣言する必要があると仮定しますが、「サブコマンダーの指す対象の型别」を型别としてどうすればいいですか?
解決方法は、function templateを利用したパラメータ導出メカニズムです。
template <class I, class T>
void func_impl(I iter, T t) {
T tmp; //
// ...
}
template <class I>
inline
void func(I iter) {
func_impl(iter, *iter); // iter iter ,class
}
int main() {
int i;
func(&i);
}
ここではすでにパッケージの意味が分かります。implのパッケージがないと、その都度表示されます。パッケージを重ねたらすっきりします。ローズマリー対応の型は「ディエゼルの指す対象の型别」だけではありません。経験によると、最も一般的な対応型は5種類ありますが、いずれも上記のtemplateパラメータ導出機構を利用して取得することができます。
関数の「templateパラメータ導出機構」で導出されたのはパラメータだけで、関数の戻り値の種類は導出できません。関数の回送値を導き出す必要があったら、どうすることもできません。
2.インサイダー宣言はいいアイデアのようです。直接に入手できます。
template <class T>
struct MyIter {
typedef T value_type; //
// ...
};
template <class I>
typename I::value_type
func(I ite) {
return *ite;
}
// ...
MyIter<int> ite(new int(8));
cout << func(ite);
見た目はいいですが、すべてのサブマシンがクラスタイプというわけではありません。class typeでないと埋め込み型を定義できません。この時は特化が必要です。
3.偏った特化とは特化に加えて制限を加えることであるが、特化したtemplateである。
template <class I>
struct iterator_traits {
typedef typename I::value_type value_type;
};
template <class I>
struct iterator_traits<T*> {
typedef T value_type;
};
template <class I>12 typename iterator_traits<I>::value_type
func(I ite) {
return *ite;
}
FncはIを呼び出す時、まずIを抽出器に伝えて、抽出器は最適なvalue_にマッチします。タイプ抽出器はまず特別なバージョンにマッチします。このように原生の指針を伝えた時に、まずマッチするのは「T*」の偏った特化バージョンです。このようにvalue_typeはTで、事前に声明していないI:value_タイプ。このように値を返すとtypename iterator_が使えます。trits:value_typeは戻りのタイプを知っています。以下に「STLソース解析」の画像を添付します。
トラストにもっと多くのことをさせます。
ローズマリーはよくある5種類のタイプがあります。value_タイプライタータイプライタータイプライターtypeはtritsと対応する偏向特化から抽出しやすいです。でも、iteratorcategoryは普通は5つもあります。これによって、大きな規模のコード作成工程が発生します。
例えば、func_を実現しました。II,func_BI,func_RAIは、それぞれ、サブエージェントタイプを表しています。Input Iterator、Bidirectional Iterator、Random Access Iteratorの対応が実現されます。
今、お客様がフルnc()を呼び出す時、判断が必要かもしれません。
template<class Iterator>
void func(Iterator& i) {
if (is_random_access_iterator(i))
func_RAI(i);
if (is_bidirectional_iterator(i))
func_BI(i);
else
func_II(i);
}
このように実行時期にどのバージョンを使うかが決定されると、プログラムの効率に影響を与えます。コンパイル期間に正確なバージョンを選択したほうがいいです。この関数機構を再負荷するとこの目標が達成できる。
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
// ...
// , input_iterator_tag
// forward_iterator_tag, ,
いくつかの列を声明したら、func関数を再搭載できます。ここまでは、各型式の具体的な積載が完了しましたが、統一されたインターフェースが必要です。この時、トレーツは出場できます。
template<class Iterator>
inline void func(Iterator& i)
{
typedef typename Iterator_traits<Iterator>::iterator_category category;
__func(i, category()); //
}
単純なインスタンスコードだから、tritsは一方で、異なる入力クラスに直面する時、適切なリターンパターンを見つけることができます。一方、パターン別対応が異なる実装関数がある場合は、パターンを抽出して分岐する役割を果たすことができる。
まず、func関数があると仮定して、カスタマイズされたクラスやオリジナルのポインタをパラメータとして受け入れて、自動的に出力して何を使っていますか?
まずtritsに従って、uの戻りパターンを抽出し、対応する構造関数return_を呼び出します。type()は、各重載バージョン_u u ufuncの重負荷フラグは、異なる実際の関数を区別します。
まず、インタフェースコードの作成を見ます。
template <class unknown_class>
inline typename unknown_class_traits<unknown_class>::return_type //
func(unknown_class u) {
typedef typename unknown_class_traits<unknown_class>::return_type return_type;
return __func(u, return_type()); // tag
}
そして設定を実現します。前述のIIやRAIなどを真似します。
template <class unknown_class>
inline typename unknown_class_traits<unknown_class>::return_type
return_type(unknown_class) {
typedef typename unknown_class_traits<unknown_class>::return_type RT;
return RT();
}
これらがあればテストできます。
struct A {};
struct B : A{};
そしてtritsが堂々と登場し、2つの偏った特化版があります。
/* */
template <class unknown_class>
struct unknown_class_traits {
typedef typename unknown_class::return_type return_type;
};
/* ―― */
template <class T>
struct unknown_class_traits<T*> {
typedef T return_type;
};
/* ―― */
template <class T>
struct unknown_class_traits<const T*> {
typedef const T return_type;
};
急に交代を忘れました。unknown_。クラスの構造、カスタムクラスは、typedefが必要です。
template <class AorB>
struct unknown_class {
typedef AorB return_type;
};
最後はfuncそれぞれのリロードバージョンです。
template <class unknown_class>
inline typename unknown_class_traits<unknown_class>::return_type
__func(unknown_class, A) {
cout << "use A flag" << endl;
return A();
}
template <class unknown_class>
inline typename unknown_class_traits<unknown_class>::return_type
__func(unknown_class, B) {
cout << "use B flag" << endl;
return B();
}
template <class unknown_class, class T>
T
__func(unknown_class, T) {
cout << "use origin ptr" << endl;
return T();
}
これらがあればテストできます。
int main() {
unknown_class<B> b;
unknown_class<A> a;
//unknown_class<int> i;
int value = 1;
int *p = &value;
A v1 = func(a);
B v2 = func(b);
int v3 = func(p);
char ch = getchar();
}
カスタムクラスで同じインターフェースに入ると、対応する関数が自動的に使用され、戻り値も適切であることが分かります。オリジナルの針にも適用されています。完璧です。付属する
以下は完全コードです。
#include <iostream>
using namespace std;
/* tag*/
struct A {};
struct B : A{}; // , A,
// B ,
/* */
template <class AorB>
struct unknown_class {
typedef AorB return_type;
};
/* */
template <class unknown_class>
struct unknown_class_traits {
typedef typename unknown_class::return_type return_type;
};
/* ―― */
template <class T>
struct unknown_class_traits<T*> {
typedef T return_type;
};
/* ―― */
template <class T>
struct unknown_class_traits<const T*> {
typedef const T return_type;
};
/* */
template <class unknown_class>
inline typename unknown_class_traits<unknown_class>::return_type
return_type(unknown_class) {
typedef typename unknown_class_traits<unknown_class>::return_type RT;
return RT();
}
template <class unknown_class>
inline typename unknown_class_traits<unknown_class>::return_type
__func(unknown_class, A) {
cout << "use A flag" << endl;
return A();
}
template <class unknown_class>
inline typename unknown_class_traits<unknown_class>::return_type
__func(unknown_class, B) {
cout << "use B flag" << endl;
return B();
}
template <class unknown_class, class T>
T
__func(unknown_class, T) {
cout << "use origin ptr" << endl;
return T();
}
template <class unknown_class>
inline typename unknown_class_traits<unknown_class>::return_type
func(unknown_class u) {
typedef typename unknown_class_traits<unknown_class>::return_type return_type;
return __func(u, return_type());
}
int main() {
unknown_class<B> b;
unknown_class<A> a;
//unknown_class<int> i;
int value = 1;
int *p = &value;
A v1 = func(a);
B v2 = func(b);
int v3 = func(p);
char ch = getchar();
}
結尾語特性抽出に時間がかかりましたが、プログラムが飛び出した瞬間はとても楽しかったです。
まず、侯捷先生に感謝します。先生の本はこんなにはっきりと説明しています。
これを見たら画像のフーリエ変換が見られます。あはは。
以上はC++trits技術についての簡単な話です。C+trits技術に関する資料は他の関連記事に注目してください。