ずっと書こうと思っていたんですが,この機会に書いてしまおうと思います.
いくつかのアルゴリズムは型の特性によって最適な実装にディスパッチしています.このような例として最も代表的なのがstd::distanceです.std::distanceはイテレータのカテゴリという標準で明記された特性タグを利用してディスパッチしています.そのため,あるプログラマが書いたイテレータであっても,そのイテレータに対するカテゴリをきちんと書いていればdistanceによるディスパッチの恩恵が受けられます.
一方で,ベンダーがアルゴリズムのために独自に用意しているtraitsも存在します.例えば,gcc(におけるSTLの実装)ではイテレータがnormalかどうか(&*iterがiterと同じsementicsを持つかどうか.例えばvector::iteratorやvector::const_iteratorは「normalの」イテレータになる)を識別する_Is_normal_iteratorというtraitsや,PODかどうかを識別する_Is_PODといったtraitsを独自に用意しています.これら独自のtraitsもいくつかのアルゴリズムのディスパッチに使用されています.例えばgccのcopyは以下のように実装されています.
- 入力と出力のイテレータがnormalかもしくはポインタで,なおかつその値がPODならmemmoveで実装
- それ以外ならfor文+代入
このようなベンダー独自のtraitsを用いたディスパッチの欠点として,ディスパッチの恩恵を受けられる範囲が固定されてしまっているということが挙げられるかと思います.上のgccの例ではPODに対するcopyだけがmemmoveによる高速化の恩恵を受けます.
もし仮に,例えばboost::has_trivial_assignが標準化されてstd名前空間に入ったり,イテレータがnormalかどうかを識別するstd::is_normal_iteratorなるtraitsが標準に追加されれば,ベンダーはこのstd::has_trivial_assignやstd::is_normal_iteratorを用いてcopyを実装するようになるでしょう.このような状況になれば,ユーザは自身が定義したクラスに対するtraitsの特殊化を書くだけでこのcopyの実装の恩恵を受けられるようになります.
struct coordinate { double x, y, z; }; namespace std{ template<> struct has_trivial_assign{ static const bool value = true; }; } std::vector u, v; /*.....*/ std::copy(u.begin(), u.end(), v.begin()); // copyがmemmoveで行われる
・・・とまぁ,こういう風になる日を夢見ているんですがまだまだ夢物語なんでしょうかね?