Vector等も渡せる配列操作関数を作成する

C++テンプレートテクニック 3-3


とりあえず例としてfindを作ってみます。

#include <iostream>
using std::cout; using std::endl;

template<class T>
T* myfind (T* first,T* last, T value) {
    T* p=first;
    for (; p != last; ++p) {
        if ( *p == value ) {
            break;
        }
    }
    return p;
}

int main () {
    int data[] = {1,2,3,4,5};
    
    // 4が存在するか
    int *p = myfind(data,data+5,4);
    
    if ( p != data+5 ) {
        cout << *p << endl;
    }
}

さてこれは何の変哲も無い値の検索ルーチンですが、このままでは単なる配列のみしか渡せず、vectorやlistといったクラスを渡せません。

そこで以下のように改良します。

#include <iostream>
#include <vector>
using std::cout; using std::endl;

template<class T,class Iterator>
Iterator myfind (Iterator first,Iterator last,T value) {
    Iterator p=first;
    for (; p != last; ++p) {
        if ( *p == value ) {
            break;
        }
    }
    return p;
}

int main () {
    std::vector<int> data;
    data.push_back(1);
    data.push_back(2);
    data.push_back(3);
    data.push_back(4);
    data.push_back(5);
    
    std::vector<int>::iterator it = myfind(data.begin(),data.end(),4);
    
    if ( it != data.end() ) {
        cout << *it << endl;
    }
}

これで配列以外でも動くようになりました。

さらにここからclass Iteratorからclass Tの型を導く方法があります。iterator_traitsを使用します。

template<class Iterator>
Iterator myfind (Iterator first,Iterator last,typename std::iterator_traits<Iterator>::value_type value) {
    Iterator p=first;
    for (; p != last; ++p) {
        if ( *p == value ) {
            break;
        }
    }
    return p;
}

これで完成です。