コンセプトを作ってみた

C++0xからConceptが導入されますが、現在のC++でも使えるConceptを作ってみました

とりあえずContainerコンセプトだけです


Containerコンセプトを使えば、コンテナと配列を同じように扱うことができます

namespace concept {

template <class T>
struct identity {
    typedef T type;
};

template <class Container>
struct container {
    typedef Container type;
    typedef typename Container::value_type      value_type;
    typedef typename Container::reference       reference;
    typedef typename Container::const_reference const_reference;
    typedef typename Container::iterator        iterator;
    typedef typename Container::const_iterator  const_iterator;
    typedef typename Container::difference_type difference_type;
    typedef typename Container::size_type       size_type;

    static iterator         begin(Container& c)         { return c.begin(); }
    static const_iterator   begin(const Container& c)   { return c.begin(); }

    static iterator         end(Container& c)           { return c.end(); }
    static const_iterator   end(const Container& c)     { return c.end(); }

    static size_type size(const Container& c) { return c.size(); }
};

template <class T, int N>
struct container<T[N]> : identity<T[N]> {
    typedef T           value_type;
    typedef T&          reference;
    typedef const T&    const_reference;
    typedef T*          iterator;
    typedef const T*    const_iterator;
    typedef T           difference_type;
    typedef std::size_t size_type;

    static iterator         begin(T (&ar)[N])       { return ar; }
    static const_iterator   begin(const T (&ar)[N]) { return ar; }

    static iterator         end(T (&ar)[N])         { return ar + N; }
    static const_iterator   end(const T (&ar)[N])   { return ar + N; }

    static size_type size(const T (&ar)[N]) { return N; }
};

} // namespace concept


使い方

template <class Container>
void foo(Container& c)
{
    typedef typename concept::container<Container> concept_type;

    typename concept_type::value_type value;
    sort(concept_type::begin(c), concept_type::end(c));
}

int main()
{
    vector<int> v;
    int ar[3];

    foo(v);  // OK
    foo(ar); // OK

    int value;
    foo(value); // エラー!

    return 0;
}

こういうふうに使えればもっと良かった(?)のですが

template <class Container>
void foo(typename concept::container<Container>::type& c)
{
}

これをやると関数テンプレートのテンプレート引数を指定しなければいけなくなります



自作コンテナを使用する場合は、containerコンセプトの要求(インターフェース)に合わせるか
containerコンセプトを特殊化してください(concept_mapみたいに)



ライブラリまとめ