views:

70

answers:

2

Hello, I would like a C++ constructor/method to be able to take any container as argument. In C# this would be easy by using IEnumerable, is there an equivalent in C++/STL ?

Anthony

+6  A: 

The C++ way to do this is with iterators. Just like all the <algorithm> functions that take (it begin, it end, ) as first two parameters.

template <class IT>
T foo(IT first, IT last)
{
    return std::accumulate(first, last, T());
}

If you really want to go passing the container itself to the function, you have to use 'template template' parameters. This is due to the fact that C++ standard library containers are not only templated with the type of the contained type, but also with an allocator type, that have a default value and is therefore implicit and not known.

#include <vector>
#include <list>
#include <numeric>
#include <iostream>

template <class T, class A, template <class T, class A> class CONT>
T foo(CONT<T, A> &cont)
{
    return std::accumulate(cont.begin(), cont.end(), T());
}

int main()
{
    std::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);

    std::list<int> l;
    l.push_back(1);
    l.push_back(2);
    l.push_back(3);

    std::cout << foo(v) << " " << foo(l) << "\n";

    return 0;
}
Didier Trosset
Also it's pretty rare for it to be useful to take a Container generically. The only member functions for a Container are begin, end, size, max_size, empty, and swap. If you have the begin/end iterators, you can do all of these except max_size (which is almost useless) and swap, although size might be much slower using the iterators. Containers also have various types, most of which you can get from the iterator_traits of the iterator. So taking any Container mostly just saves typing. Being a bit more specific (taking a Sequence, for instace) might be more useful.
Steve Jessop
+1  A: 

Depends what you want to do with the container. One thought: just pass an iterator if you want to access what is stored in the container.