1

I am new to generic functions in C++. I have a template function that prints the inside of a vector.

template<class T>
void print(vector<T> v){
    for(typename vector<T>::iterator it=v.begin(); it != v.end() ; it++)
        cout << *it << endl;
}

I want to write a more generic print() to print an STL container's inside. How can I proceed from this point on?

Varaquilex
  • 3,447
  • 7
  • 40
  • 60

1 Answers1

5

There's already a generic algorithm that can do that, using iterators for both the input and the output:

std::copy(v.begin(), v.end(), std::ostream_iterator<T>(std::cout, "\n"));

As such, I would proceed by using what's already there. If you really like the syntax of print(container_name); (which I'll admit is attractive), you could use this as the implementation, something like this:

template <class Container>
void print(Container const &c) { 
    std::copy(std::begin(c), std::end(c),
              std::ostream_iterator<typename Container::value_type>(std::cout, "\n"));
}

I'd note that (in C++11) it's often more convenient to use a range-based for loop than std::copy though:

template <class Container>
void print(Container const &c) { 
    for (auto const &item : c)
        std::cout << item << "\n";
}

Either of these should work for most real containers, though I'd generally prefer the latter, not only because it's simpler, but also because it's a little more generic. The first requires an actual container the defines a value_type member, so you can't apply it to a built-in array, for one example. You can remove that particular limitation by using std::iterator_traits<iterator>::value_type if you want to badly enough, but the latter avoids the problem entirely (and simplifies the code quite a bit in the process).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • @SteveJessop: Sorry--accidentally posted before I really finished the post. I *think* it covers most of your concerns a little more completely now. – Jerry Coffin Nov 27 '13 at 23:56
  • +1 for mentioning C++11. This really is a neat answer. Thank you @JerryCoffin . – Varaquilex Nov 28 '13 at 00:09
  • is `main.cpp:31:10: error: ‘begin’ is not a member of ‘std’ copy(std::begin(c), end(c),` normal? Do I need a particular library to include for `begin()` and `end()` ? – Varaquilex Nov 28 '13 at 00:20
  • 1
    @Volkanİlbeyli: Sounds like you're using an older (Pre-C++11) compiler (or at least an older library, anyway). Try `c.begin()` and `c.end()` instead. – Jerry Coffin Nov 28 '13 at 06:56