Reputation: 10497
I've got a very simple test program like below:
#include<vector>
#include<iostream>
using namespace std;
template<typename C, typename E>
void f(const C<E>& container){
cout<<container.size()<<endl;
}
int main(){
vector<int> i;
f(i);
return 0;
}
It fails to compile with gcc 4.1.2. Error message is:
templateContainer.cpp:5: error: ‘C’ is not a template
templateContainer.cpp: In function ‘int main()’:
templateContainer.cpp:10: error: no matching function for call to ‘f(std::vector<int, std::allocator<int> >&)’
Upvotes: 4
Views: 1364
Reputation: 67723
Although WhiZTiM's answer is correct (well, preferring the second part), it doesn't explain why your code doesn't work.
Assuming for the moment that you intended roughly
template<template <typename> class C, typename E> void f(const C<E>&);
the reason that std::vector
doesn't match is that it is the wrong shape - it has two type parameters, not one as in your declaration.
Just because you don't often explicitly write the defaulted second (allocator) param, doesn't mean it isn't there.
For comparison, this works (or doesn't) in an analogous way:
void f(int);
void g(int, int* = nullptr);
void apply(void (*func)(int), int);
apply(f, 42); // ok - f matches shape void(*)(int)
apply(g, 42); // error - g is really void(*)(int,int*)
specifically, default arguments (or type parameters) are syntactic sugar. They allow you to forget about those arguments at the call (instantiation) site, but don't change the shape of the function (or template).
Upvotes: 2
Reputation: 1120
std::vector has two template arguments, type and allocator.
template <template<class, class> class C, class E, class A>
void f(const C<E, A> &container)
{
std::cout << container.size() << endl;
}
int main()
{
std::vector<int> i;
f(i);
return 0;
}
Upvotes: 2
Reputation: 21576
You could use a template template parameter (and note that std::vector
actually takes more than one template parameter [an element type, and an allocator type]).:
template<template <typename...> class C, typename... E>
void f(const C<E...>& container){
cout<<container.size()<<endl;
}
If you don't need the type decompositions, you could simply use an ordinary template.
template<typename C>
void f(const C& container){
cout<<container.size()<<endl;
}
You can additionally obtain typedefs from STL containers: for example, if you want to know the type of elements held by the container, value_type
is there for you.
template<typename C>
void f(const C& container){
using ValueType = typename C::value_type;
cout<<container.size()<<endl;
}
Upvotes: 12