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

コンテナの結合(join)

C++

http://d.hatena.ne.jp/uskz/20071212/p7
で見たid:mb2syncさん作成のpstade::oven::jointedがおもしろかったので(jointedのソースは見てないですけど)
似たようなのを作ってみました


同じ型を格納しているコンテナや配列を結合し、一度のループで全てを走査できます



使い方

#include <iostream>
#include <vector>
#include <list>
#include <shand/algorithm.hpp>  // copy
#include <shand/join.hpp>       // join
#include <shand/assign/std.hpp> // extension vector/list operator+=
#include <shand/foreach.hpp>    // foreach
#include <boost/foreach.hpp>    // BOOST_FOREACH

using namespace std;
using namespace shand;
using namespace shand::assign;

int main()
{
    int ar[] = {1, 2, 3};

    vector<int> v;
    v += 4, 5, 6;

    list<int> li;
    li += 7, 8, 9;

    copy(join(ar, v, li), ostream_iterator<int>(cout, "\n"));

    foreach (int value, join(ar, v, li))
        cout << value << endl;

    for each (int value in join(ar, v, li)) // ※VC++8.0以降のfor each
        cout << value << endl;

    BOOST_FOREACH (int value, join(ar, v, li))
        cout << value << endl;

	return 0;
}
1
2
3
4
5
6
7
8
9
...

これは

foreach (int value, join(ar, v, li))
    cout << value << endl;


こう書いてもいい

foreach (int value, join(ar)|join(v)|join(li)))
    cout << value << endl;

前者の書き方は最大10個まで




以下ソース(join.hpp)

#ifndef SHAND_JOIN_INCLUDE
#define SHAND_JOIN_INCLUDE

#include <iterator>
#include <vector>
#include <algorithm>

namespace shand {

    namespace join_detail {
        // range begin, end
        template <class Type, int Size>
        inline Type* begin(Type (&ar)[Size]) { return ar; }

        template <class Type, int Size>
        inline Type* end(Type (&ar)[Size]) { return ar + Size; }

        template <class Container>
        inline typename Container::iterator begin(Container& c) { return c.begin(); }

        template <class Container>
        inline typename Container::const_iterator begin(const Container& c) { return c.begin(); }

        template <class Container>
        inline typename Container::iterator end(Container& c) { return c.end(); }

        template <class Container>
        inline typename Container::const_iterator end(const Container& c) { return c.end(); }

        // range_value
        template <class Container>
        struct range_value {
            typedef typename Container::value_type type;
        };

        template <class Type, int Size>
        struct range_value< Type[Size] > {
            typedef Type type;
        };

        template <class Type, int Size>
        struct range_value< const Type[Size] > {
            typedef Type type;
        };

    } // namespace shand::join_detail

template <class Type>
class jointer {
    std::vector<Type> elements_;

public:
    typedef Type                                        value_type;
    typedef Type                                        difference_type;
    typedef Type&                                       reference;
    typedef typename std::vector<Type>::iterator        iterator;
    typedef typename std::vector<Type>::const_iterator  const_iterator;

    template<class Iterator>
    jointer(Iterator first, Iterator last) : elements_(first, last) {}

    iterator        begin()         { return elements_.begin(); }
    const_iterator  begin() const   { return elements_.begin(); }
    iterator        end()           { return elements_.end(); }
    const_iterator  end() const     { return elements_.end(); }

    template <class Iterator>
    void push(Iterator first, Iterator last) { std::copy(first, last, std::back_inserter(elements_)); }
};

template <class T0, class T1>
inline jointer<T0> operator|(const jointer<T0>& lhs, const jointer<T1>& rhs)
{
    jointer<T0> c(join_detail::begin(lhs), join_detail::end(lhs));
    c.push(join_detail::begin(rhs), join_detail::end(rhs));
    return c;
}

template <class Container>
inline jointer<typename join_detail::range_value<Container>::type> join(const Container& c)
{
    return jointer<typename join_detail::range_value<Container>::type>(join_detail::begin(c), join_detail::end(c));
}


// variadic join
template <class T0, class T1>
inline jointer<typename join_detail::range_value<T0>::type> join(const T0& t0, const T1& t1)
{
    return join(t0)|join(t1);
}

template <class T0, class T1, class T2>
inline jointer<typename join_detail::range_value<T0>::type> join(const T0& t0, const T1& t1, const T2& t2)
{
    return join(t0, t1)|join(t2);
}

template <class T0, class T1, class T2, class T3>
inline jointer<typename join_detail::range_value<T0>::type> join(const T0& t0, const T1& t1, const T2& t2, const T3& t3)
{
    return join(t0, t1, t2)|join(t3);
}

template <class T0, class T1, class T2, class T3, class T4>
inline jointer<typename join_detail::range_value<T0>::type> join(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
                                                                 const T4& t4)
{
    return join(t0, t1, t2, t3)|join(t4);
}

template <class T0, class T1, class T2, class T3, class T4, class T5>
inline jointer<typename join_detail::range_value<T0>::type> join(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
                                                                 const T4& t4, const T5& t5)
{
    return join(t0, t1, t2, t3, t4)|join(t5);
}

template <class T0, class T1, class T2, class T3, class T4, class T5, class T6>
inline jointer<typename join_detail::range_value<T0>::type> join(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
                                                                 const T4& t4, const T5& t5, const T6& t6)
{
    return join(t0, t1, t2, t3, t4, t5)|join(t6);
}

template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
inline jointer<typename join_detail::range_value<T0>::type> join(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
                                                                 const T4& t4, const T5& t5, const T6& t6, const T7& t7)
{
    return join(t0, t1, t2, t3, t4, t5, t6)|join(t7);
}

template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
inline jointer<typename join_detail::range_value<T0>::type> join(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
                                                                 const T4& t4, const T5& t5, const T6& t6, const T7& t7,
                                                                 const T8& t8)
{
    return join(t0, t1, t2, t3, t4, t5, t6, t7)|join(t8);
}

template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
inline jointer<typename join_detail::range_value<T0>::type> join(const T0& t0, const T1& t1, const T2& t2, const T3& t3,
                                                                 const T4& t4, const T5& t5, const T6& t6, const T7& t7,
                                                                 const T8& t8, const T9& t9)
{
    return join(t0, t1, t2, t3, t4, t5, t6, t7, t8)|join(t9);
}


} // namespace shand

#endif // SHAND_JOIN_INCLUDE


※なお、join作成に伴い、foreachを一部修正していますので、修正内容はそちらをご参照ください



ライブラリまとめ