Reputation: 6546
I want to write a function that takes a generic container with any type and prints it.
Let's leave for a moment that it won't work for some associative containers and focus on the issue:
template<template<typename> typename Cont, typename T>
void print(const Cont<T>& cont)
{
for (const auto it : cont)
{
cout << it << " ";
}
cout << endl;
}
int main()
{
vector<string> v;
print(v);
}
The error states:
error C2672: 'print': no matching overloaded function found
error C3207: 'print': invalid template argument for 'Cont', class template expected
Can anyone please explain why the compiler cannot deduce the types here?
Even when I explicitly state print<vector<string>>(v)
?
Upvotes: 2
Views: 701
Reputation: 32722
std::vector
has more than one class-template-args.
template<
class T, // -----------> you have mentioned!
class Allocator = std::allocator<T> // -----> this didn't!
> class vector;
But you have provided only one. This is the reason for the no matching overloaded compiler error.
In order to fix the issue, you need to provide the variadic args in the template template arg.
template<template<typename...> typename Cont, typename T>
// ^^^^^^^^^^^^^^^^^^^^
void print(const Cont<T>& cont)
{
for (const auto& it : cont) {
std::cout << it << " ";
}
std::cout << std::endl;
}
However, you could have done this simply
template <typename Cont>
void print(const Cont& cont)
{
// ...
}
Or like the standard way, passing the begin and end iterator of the container to the function
#include <algorithm> // std::copy
#include <iterator> // std::iterator_traits
template<typename Iterator>
constexpr void print(const Iterator begin, const Iterator end) noexcept
{
using ValueType = typename std::iterator_traits<Iterator>::value_type;
std::copy(begin, end, std::ostream_iterator<ValueType>(std::cout, " "));
std::cout << "\n";
}
and call it like
print(v.begin(), v.end());
Upvotes: 5
Reputation: 206567
std::vector
is defined as
template<
class T,
class Allocator = std::allocator<T>
> class vector;
std::vector
is a class template with two template parameters. It does not match
the template template parameter of your function.
Change it to
template <typename Cont>
void print(const Cont& cont)
{
for (const auto& elem : cont) {
std::cout << elem << " ";
}
std::cout << std::endl;
}
You can deduce T
from the container, if that is necessary.
Upvotes: 3