recently i was testing some c++ template codes and i found one mind-boggling error. According to my research on internet in particular stackoverflow, this code is completely valid however, compiler raises compile time error. Error is located below of code.
Code:
template<template<class> class C, typename T> void print(C<T>& c) {
}
int test() {
vector<string> v(5, "Yow!");
print(v);
return 0;
}
Compiler Output:
In function ‘int test()’:
error: no matching function for call to ‘print2(std::vector<std::basic_string<char> >&)’
note: candidate is:
note: template<template<class> class C, class T> void print2(C<T>&)
It seems something is wrong about definition or my compiler but i tested this code with both g++ and clang++ in order to be sure about there is not any compiler dependent problem. Both of them raises same error.
I really appreciate any meaningful comments which aim to make clarification for this problem.
Thank you
std::vector
, the type being passed in as C
, has more than one template parameter. It has the usual element type, but also an allocator. The easiest way to get around this while keeping a list of type arguments is to use a variadic template:
template<template<class...> class C, typename... Ts> void print(C<Ts...>& c)
^^^^^^^^ ^^^^^^ ^^^^^^^^
Actually using the individual type arguments is easier done, in most cases, by explicitly specifying them, as in Cheers' answer. If you don't care about the type arguments, feel free to not keep track of them. In the case of a container, you can even get them from just the container type:
template<typename Container> void print(Container& c) {
typename Container::value_type t;
}
Expanding on chris' answer, the following compiles fine with both visual c++ 12.0 and g++ 4.7.2:
#include <vector>
#include <string>
using namespace std;
template<template<class, class> class C, class T, class U> void print(C<T, U>& c)
{ (void) c; }
void test() {
vector<string> v(5, "Yow!");
print(v);
}
However, if you really just want to output the items of a container, why not do this instead:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
template< class C >
void print( C const& c )
{
for( auto const& item : c )
{
cout << item << endl;
}
}
auto main() -> int
{
vector<string> v(5, "Yow!");
print(v);
}