0

I am trying to write a function to print std list in C++. Is it true that for template function, T cannot be used as template argument?

template <typename T>
void printlist(list<T> a)
{
    list<T>::iterator i;
    for (i=a.begin(); i!=a.end(); ++i)
        cout<<*i<<" ";
}
Dzung Nguyen
  • 3,794
  • 9
  • 48
  • 86
  • 1
    I am not sure, but have you tried to build it? – hamon Nov 02 '13 at 22:07
  • 1
    I'm not sure what exactly you mean, but you need `typename` before `list::iterator` and then all is well. – jrok Nov 02 '13 at 22:09
  • 1
    http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords – CB Bailey Nov 02 '13 at 22:09
  • As a general rule, if you use a templated type as a parameter for another template, you need to add `typename` in the front to tell the compiler to resolve it.(sounds stupid I know but it is how it works) – SwiftMango Nov 02 '13 at 22:16

3 Answers3

4

The code is mostly legal. Some compilers may accept it...however, writing it the following way is sure to work (assuming you have using namespace std defined):

template <typename T>
void printlist(list<T> a)
{
    typename list<T>::iterator i;
    for (i=a.begin(); i!=a.end(); ++i)
        cout<<*i<<" ";
}

For efficiency, you should pass in the list as a const reference:

template <typename T>
void printlist(const list<T>& a)
{
    typename list<T>::const_iterator i;
    for (i=a.begin(); i!=a.end(); ++i)
        cout<<*i<<" ";
}

However, there is an STL algorithm that already does this for you. Assuming you want to print out a list of integers, just write:

copy( a.begin(), a.end(), ostream_iterator<int>( cout, " " ) );

Just replace int with the appropriate element type. Note: This algorithm works on any sequence.

MarkB
  • 872
  • 5
  • 13
3

Seems like you are using C++03 standards where in order to parse a C++ program, compiler need to know for certain names whether they names are types or non-types.

As a fix to your problem you need to add typename before list<T>::iterator to make it work

template <typename T>
void printlist(list<T> a)
{
    typename list<T>::iterator i;
    for (i=a.begin(); i!=a.end(); ++i)
        cout << *i << " ";
}
Vishnu Kanwar
  • 761
  • 5
  • 22
-2

Are you sure that the template name list is resolving to std::list?

EDIT: you forgot the typename keyword. The compiler error message will almost always say "typename required for dependent types". This underscores the need to include error messages when posting about problems.

Other feedback:

  • It's not good practice to construct an iterator like i and then initialize it later. It would be better to write list<T>::iterator i = a.begin(); This could be part of your for loop.
  • You could use a const_iterator
  • You are passing a list by value, instead of by const reference. In other words, this declaration would be better: void printlist(const std::list<T>& a)
NicholasM
  • 4,557
  • 1
  • 20
  • 47