STL iterator traitor


反復器の型別(associated types)は汎用プログラミングでよく用いられる技術である.C++は弱い言語であるためtypeof()はサポートされていない.RTTIのtypeid()は使用できますが、得られるのは型別の名前であり、変数の宣言には使用できません.
解決策はテンプレート関数のパラメータで倒すことができる(argument deducation)
#include<iostream>
using namespace std;

template<class I, class T>
void func_impl(I iter, T t)
{
    T tmp;
    tmp = *iter;
    cout<<tmp<<endl;
    //do something ...
}

template<class I>
void func(I iter)
{
    func_impl(iter, *iter);
}

int main()
{
    int i = 10;
    func(&i);
}

しかし,反復器の型別は必ずしも反復器自身の型を指すものではない.したがって,上記の方法ではすべての問題を解決することはできない.
インライン宣言を使用できます
#include<iostream>
#include<string>
#include<vector>
using namespace std;

template<class T>
struct MyIter {
    typedef T value_type;
    T* ptr;
    MyIter(T* p): ptr(p) {}
    T& operator* () const { return *ptr; }
};
template<class T>
typename my_iterator_traits<T>::value_type
func(T iter)
{ return *iter; }

int main()
{
    MyIter<int> iter(new int(10));
}
しかし、すべての反復器がclassタイプであるわけではありません.ポインタの場合、上記の方法は機能しません.私たちは彼のclass typeを定義できないからです.
これは偏特化(Partial Specialization)が必要です
#include<iostream>
#include<string>
#include<vector>
using namespace std;

template<class T>
struct MyIter {
    typedef T value_type;
    T* ptr;
    MyIter(T* p): ptr(p) {}
    T& operator* () const { return *ptr; }
};

template<class T>
struct my_iterator_traits{
    typedef typename T::value_type value_type;
};

template<class T>
struct my_iterator_traits<T*>{
    typedef T value_type;
};

template<class T>
typename my_iterator_traits<T>::value_type
func(T iter)
{ return *iter; }

int main()
{
    MyIter<int> iter(new int(10));
    int p = 16;
    cout<<func(&p)<<endl;
}