Fast STL-container concatination iterator?

Hi,

has anyone an iterator template lying around his toolbox which iterates over two STL containers? Couldn't find one in boost. Basically, I want to use one for-loop to iterate over two identical-typed containers in one go. (Wouldn't harm if it supports more than two and non-identical containers ;) )

I came up with a version of myself only supporting plain iteration. (Warning: It is HORRIBLE fragile in usage. Sneeze and you get a segfault). But it only has one boolean compare per operator++ overhead.

If I understand it correctly, this is the smallest overhead possible without changing the container before and after the iteration. (Anyone has a concatination iterator template that *does* change the container and so achieve better performance for containers where it's possible to do so?)


Anyway, here is my version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
template<class Container>
struct combine
{
    typedef typename Container::iterator CIt;
    struct It : CIt
    {
        CIt end1_, begin2_;
        bool withinC2_;
        It(const CIt& it, const CIt& end1, const CIt& begin2, bool withinC2)
            : CIt(it), end1_(end1), begin2_(begin2), withinC2_(withinC2) {}
        It& operator++()
        {
            CIt::operator++();
            if (!withinC2_ && static_cast<const CIt&>(*this) == end1_)
            {
                CIt::operator=(begin2_);
                withinC2_=true;
            }
            return *this;
        }
        bool operator==(const It& rhs) const { return withinC2_ == rhs.withinC2_ && static_cast<const CIt&>(*this) == rhs; }
        bool operator!=(const It& rhs) const { return withinC2_ != rhs.withinC2_ || static_cast<const CIt&>(*this) != rhs; }
    private:
        It operator++(int); // undefined
    };
    typedef It iterator;

    Container &c1_, &c2_;
    combine(Container& c1, Container& c2) : c1_(c1), c2_(c2) {}
    It begin() { return It(c1_.begin(), c1_.end(), c2_.begin(), false); }
    It end() { return It(c2_.end(), c1_.end(), c2_.begin(), true); }
};

// some performance measurement
int main()
{
    list<int> l(10000000), l2(10000000);
    long before, after;
    
    before = clock();
    for(auto it = l.begin(), e = l.end(); it != e; ++it)
        *it = rand();
    for(auto it = l2.begin(), e = l2.end(); it != e; ++it)
        *it = rand();
    after = clock();
    cout << after-before << endl;

    before = clock();
    combine<list<int>> c(l,l2);
    for(auto it = c.begin(), e = c.end(); it != e; ++it)
        *it = rand();
    after = clock();
    cout << after - before << endl;
}

Last edited on
Topic archived. No new replies allowed.