16
16
- [ ポリシークラス(Policy Classes)] ( #policy-classes )
17
17
18
18
19
- ## <a name =" introduction " href =" #introduction " >はじめに(Introduction)</a >
19
+ ## <a id =" introduction " href =" #introduction " >はじめに(Introduction)</a >
20
20
ジェネリックプログラミングはソフトウェアコンポーネントに汎用化に関するものであり、 これによりコンポーネントを多様な状況で容易に再利用することが出来る。 C++ ではクラステンプレートと関数テンプレートがジェネリックプログラミング技術に対して特に効果的である。 なぜなら、これらは効率を犠牲にすることなく汎用化を可能にするからである。
21
21
22
22
ジェネリックプログラミングの簡単な例として、C 標準ライブラリの ` memcpy() ` 関数をどのように汎用化するか見てみよう。 ` memcpy() ` の実装は次のようになっている。
@@ -73,7 +73,7 @@ int main()
73
73
}
74
74
```
75
75
76
- ## <a name =" the-anatomy-of-a-concept " href =" #the-anatomy-of-a-concept " >コンセプトの分析(The Anatomy of a Concept)</a >
76
+ ## <a id =" the-anatomy-of-a-concept " href =" #the-anatomy-of-a-concept " >コンセプトの分析(The Anatomy of a Concept)</a >
77
77
** コンセプト** は要求の集合であり、要求は有効な式、関連型、不変量、 そして計算量の保証から出来ている。要求の集合を満たす型は、コンセプトの モデル と言われる。 コンセプトは他のコンセプトの要求を拡張することが可能であり、これは ** 発展型(refinement)** と呼ばれる。
78
78
79
79
- ** 有効な式** とは、 コンセプトの * モデル* とみなされる式に関わるオブジェクトに対して、 コンパイルが成功しなければならない C++ の式である。
@@ -84,7 +84,7 @@ int main()
84
84
C++ 標準ライブラリで使われているコンセプトは [ SGI STL site] ( http://www.sgi.com/tech/stl/table_of_contents.html ) で文書化されている。
85
85
86
86
87
- ## <a name =" traits " href =" #traits " >特性クラス(Traits)</a >
87
+ ## <a id =" traits " href =" #traits " >特性クラス(Traits)</a >
88
88
特性クラスは、コンパイル時の実体(型、汎整数定数、アドレス)に情報を関連付ける手段を提供する。例えば、クラステンプレート` std::iterator_traits<T> ` は次のようになっている:
89
89
90
90
``` cpp
@@ -105,7 +105,7 @@ struct iterator_traits {
105
105
`std::iterator_traits` についての詳細な記述は、 SGI が提供している [このページ](http://www.sgi.com/tech/stl/iterator_traits.html) を見よ。 標準ライブラリでの、大きく異なる別の特性の式は `std::numeric_limits<T>` である。これは、 数値型の範囲と能力を記述する定数を提供している。
106
106
107
107
108
- ## <a name ="tag-dispatching" href="#tag-dispatching">タグ分岐(Tag Dispatching)</a>
108
+ ## <a id ="tag-dispatching" href="#tag-dispatching">タグ分岐(Tag Dispatching)</a>
109
109
特性クラスと同時に使われることが多い技術に、タグ分岐がある。 これは、型の性質に基づいて分岐するために、関数オーバーロードを使う方法である。 これについてのよい例は、C++ 標準ライブラリの [`std::advance()`](http://www.sgi.com/tech/stl/advance.html) 関数である。 これは、イテレータを `n` 回インクリメントする。 イテレータの種類によって、実装の中では適用される、異なる最適化がある。 もしイテレータが [random access](http://www.sgi.com/tech/stl/RandomAccessIterator.html) (前方、後方に任意の距離、ジャンプすることが可能である) なら、 `advance()` 関数は単に `i += n` で実装され、これは非常に効率的、つまり定数時間である。 他のイテレータでは、 ステップ数が **上昇** し、演算は `n` に対する線形時間になる。 もしイテレータが、 [双方向](http://www.sgi.com/tech/stl/BidirectionalIterator.html) なら、 `n` が負であっても良いので、 イテレータをインクリメントするかデクリメントするか選ばなければならない。
110
110
111
111
タグ分岐と特性クラスの関係は、分岐に使われる性質(この場合では `iterator_category`) が特性クラスによってアクセスされることが多い、ということである。 主たる `advance()` 関数は `iterator_category` を得るために [`iterator_traits`](http://www.sgi.com/tech/stl/iterator_traits.html) クラスを使う。 それから、オーバーロードされた `advance_dispatch()` 関数を呼び出すのである。 `iterator_category` をどんな型に解決するかに基づいて、 コンパイラにより、 [`input_iterator_tag`](http://www.sgi.com/tech/stl/input_iterator_tag.html) か [`bidirectional_iterator_tag`](http://www.sgi.com/tech/stl/bidirectional_iterator_tag.html) か [`random_access_iterator_tag`](http://www.sgi.com/tech/stl/random_access_iterator_tag.html) の中から適した `advance_dispatch()` が選ばれるのである。 **タグ** はタグ分岐や、似たような技術で使うための性質を伝える、 という目的だけを持つ単純なクラスである。 イテレータタグのより詳細な記述については、[このページ](http://www.sgi.com/tech/stl/iterator_tags.html) を参照すること。
@@ -147,13 +147,13 @@ namespace std {
147
147
```
148
148
149
149
150
- ## <a name =" adaptors " href =" #adaptors " >アダプタ(Adaptors)</a >
150
+ ## <a id =" adaptors " href =" #adaptors " >アダプタ(Adaptors)</a >
151
151
* アダプタ* は別の型や、新しいインタフェース、振る舞いの変種を提供する型を構築する、 クラステンプレートである。 標準のアダプタの例は、 [ ` std::reverse_iterator ` ] ( http://www.sgi.com/tech/stl/ReverseIterator.html ) にある。これは、インクリメント、デクリメントに対しその動きを逆転させる、イテレータ型に対するアダプタである。 [ ` std::stack ` ] ( http://www.sgi.com/tech/stl/stack.html ) は単純なスタックインタフェースを提供するコンテナに対するアダプタである。
152
152
153
153
標準でのアダプタについての、より解りやすいレビューは [ ここ] ( http://www.cs.rpi.edu/~wiseb/xrds/ovp2-3b.html#SECTION00015000000000000000 ) にある。
154
154
155
155
156
- ## <a name =" type-generators " href =" #type-generators " >型生成器(Type Generators)</a >
156
+ ## <a id =" type-generators " href =" #type-generators " >型生成器(Type Generators)</a >
157
157
* 型生成器* はテンプレート引数 [ ^ 1 ] に基づいて新しい型を合成することだけが目的のテンプレートである。 生成された型は通常、ネストされた ` typedef ` として表現され、いかにもふさわしく ` type ` と命名される。 型生成は通常、複雑な型表現をひとつの型に統合するために使われる。例えば、 ` boost::filter_iterator_generator ` では、次のようになっている:
158
158
159
159
``` cpp
@@ -178,7 +178,7 @@ boost::filter_iterator_generator<my_predicate,my_base_iterator>::type
178
178
```
179
179
180
180
181
- ## <a name =" object-generators " href =" #object-generators " >オブジェクト生成器(Object Generators)</a >
181
+ ## <a id =" object-generators " href =" #object-generators " >オブジェクト生成器(Object Generators)</a >
182
182
* オブジェクト生成器* は関数テンプレートであり、唯一の目的は、 引数から新しいオブジェクトを構築することである。 汎用コンストラクタの一種として考えることが出来るだろう。 オブジェクト生成器は、生成される実際の型を表現するのが難しかったり、出来なかったりするときに、 単なるコンストラクタよりも役立つだろう。 そして生成器の結果は変数に格納するのではなく、直接関数に渡すことも出来る。 多くの Boost オブジェクト生成器は接頭辞 "` make_ ` " がつけられている。 これは、` std::make_pair(const T&, constU&) ` に倣ってのことである。
183
183
184
184
たとえば、次のようなものを考えてみる:
@@ -214,7 +214,7 @@ void tweak_all_widgets2(int arg)
214
214
表現がより複雑になるにつれて、型指定の冗長性を減らす必要性はどうしても大きくなるのである。
215
215
216
216
217
- ## <a name ="policy-classes" href="#policy-classes">ポリシークラス(Policy Classes)</a>
217
+ ## <a id ="policy-classes" href="#policy-classes">ポリシークラス(Policy Classes)</a>
218
218
ポリシークラスは振る舞いを伝達するために使われるテンプレート引数である。 標準ライブラリからの例は `std::allocator` である。これは、メモリ管理の振る舞いを標準の containers に伝える。
219
219
220
220
ポリシークラスは Andrei Alexandrescu によって、 [この文書](http://www.cs.ualberta.ca/~hoover/cmput401/XP-Notes/xp-conf/Papers/7_3_Alexandrescu.pdf) の中で詳しく探求されている。彼は次のように書いている:
0 commit comments