First note that if referring to a template argument dependent name like vector<T>::iterator
here, then you need to put typename
prior. Furthermore, depends on what T
is, this would only compile if std::cout
's operator<<
is accepting this T
. This, for example, compiles just fine:
#include <iostream>
#include <vector>
template <typename T>
void showset(std::vector<T> v)
{
for (typename std::vector<T>::iterator it = v.begin(); it != v.end(); it++)
{
std::cout << *it;
}
std::cout << std::endl;
}
struct foo
{
};
int main()
{
showset(std::vector<int>{1,2,3});
//showset(std::vector<foo>{}); // Error: `cout` doesn't take `foo`s.
return 0;
}
With the auto
-enhanced syntax of C++11, showset()
could be written like this, and then the typename
has no use : )
template <typename T>
void showset(std::vector<T> v)
{
for (auto it = v.begin(); it != v.end(); it++)
{
std::cout << *it;
}
std::cout << std::endl;
}
Also since C++11, you can use the range-based for loop to achieve the same as in your original snippet:
template <typename T>
void showset(std::vector<T> v)
{
for (auto& ref : v)
{
std::cout << ref;
}
std::cout << std::endl;
}
As with the lase version, because you're not referring here to the iterator
type there's nothing to put typename
for.
Do note that in both versions you are taking parameter v
by value. Hence, you're copying the entire vector for each function call. As the code is given in the question, there seem to be no reason for this and so you should be passing it by reference, and make it a const
one too as you're not modifying v
anywhere inside of showset()
:
void showset(const std::vector<T>& v);
and then in the non-range-based for loop version don't forget to change the loop statement accordingly:
for (typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); it++)