読者です 読者をやめる 読者になる 読者になる

C++0x concept_mapはAdapterパターンとして使える

C++

コンテナに要素を追加する場合、 vector::push_back, set::insert, stack::push を
同じように使いたいということがあって、そういう場合 C++03 では以下のようにします

#include <vector>
#include <set>
#include <stack>

using namespace std;

template <class Container, class T>
inline void add(Container& c, const T& value)
{
    c.push_back(value);
}

template <class T, class U>
inline void add(set<T>& c, const U& value)
{
    c.insert(value);
}

template <class T, class U>
inline void add(stack<T>& c, const U& value)
{
    c.push(value);
}

int main()
{
    vector<int> v;
    set<int>    st;
    stack<int>  sk;

    add(v,  3); // v.push_back(3);
    add(st, 1); // st.insert(1);
    add(sk, 4); // sk.push(4);

    return 0;
}


concept_map 使うと以下のように書けます

#include <vector>
#include <set>
#include <stack>

concept AddAdapter<class X> {
    typename value_type;

    void add(X&, const value_type&);
}


template <class T>
concept_map AddAdapter<std::vector<T>> {
    typedef typename std::vector<T>::value_type value_type;

    void add(std::vector<T>& v, const value_type& val)
    {
        v.push_back(val);
    }
}


template <class T>
concept_map AddAdapter<std::set<T>> {
    typedef typename std::set<T>::value_type value_type;

    void add(std::set<T>& s, const value_type& val)
    {
        s.insert(val);
    }
}


template <class T>
concept_map AddAdapter<std::stack<T>> {
    typedef typename std::stack<T>::value_type value_type;

    void add(std::stack<T>& s, const value_type& val)
    {
        s.push(val);
    }
}


template <AddAdapter adapter>
void add(adaptoe& adter, const adaptor::value_type& val)
{
    add(adter, val);
}

int main()
{
    std::vector<int> v;
    std::set<int>    st;
    std::stack<int>  sk;

    add(v,  3); // v.push_back(3);
    add(st, 1); // st.insert(1);
    add(sk, 4); // sk.push(4);
}

う〜ん、なんかめんどくさいな

#include <vector>
#include <set>
#include <stack>

auto concept HasPushBack<class X> {
    typename value_type = X::value_type;
    void X::push_back(const value_type&);
}

auto concept HasInsert<class X> {
    typename value_type = X::value_type;
    void X::insert(const value_type&);
}

auto concept HasPush<class X> {
    typename value_type = X::value_type;
    void X::push(const value_type&);
}


template <HasPushBack Cont>
void add(Cont& c, const Cont::value_type& val)
{
    c.push_back(val);
}

template <HasInsert Cont>
void add(Cont& c, const Cont::value_type& val)
{
    c.insert(val);
}

template <HasPush Cont>
void add(Cont& c, const Cont::value_type& val)
{
    c.push(val);
}


int main()
{
    std::vector<int> v;
    std::set<int>    st;
    std::stack<int>  sk;

    add(v,  3); // v.push_back(3);
    add(st, 1); // st.insert(1);
    add(sk, 4); // sk.push(4);
}

Concept-based オーバーロードのほうがラクかも