Reputation: 12087
I'm trying to use different types of containers of different types with the same function but couldn't convince my compiler. Here are some of the things I have tried:
#include <iostream>
#include <vector>
#include <list>
using namespace std;
// error: expected a qualified name after 'typename'
template<typename C<T>>
void func1() {
C<T> c;
c.push_back(new T);
}
// error: expected a qualified name after 'typename'
template<typename C<typename T>>
void func2() {
C<T> c;
c.push_back(new T);
}
// error: expected a qualified name after 'typename'
template<typename C<template <typename T>>>
void func3() {
C<T> c;
c.push_back(new T);
}
int main(int argc, char *argv[]) {
func1<vector<int>>();
func1<list<float>>();
func2<vector<int>>();
func2<list<float>>();
func3<vector<int>>();
func3<list<float>>();
return 0;
}
Is this possible in C++?
Upvotes: 2
Views: 982
Reputation: 5808
The closest I think you can get to your original code (assuming you wanted two parameters, C
and T
and not just one C<T>
) is the following:
#include <iostream>
#include <vector>
#include <list>
using namespace std;
template<template< class T, class A = allocator<T> > class C, typename T>
void func() {
C<T*> c;
c.push_back(new T);
}
int main(int argc, char *argv[]) {
func<vector, int>();
func<list, float>();
return 0;
}
Notice two things:
The vector
and list
templates take two parameters, the second one defaulting to allocator<T>
(where T
is the first parameter). You cannot define the template with just one parameter; the type system will complain when instantiating.
If you have a container of type C<T>
with a push_back
method expecting a T
(like vector
and list
), you cannot pass it new T
as a parameter. I took the liberty of fixing the container to be of type C<T*>
.
Upvotes: 3
Reputation: 14174
I think you are talking about "template template parameters".
Template-template parameters are a kind of type template parameters which template classes are allowed only. That class template could have any kind of template parameters. For example:
template<template<typename T , typename ALLOCATOR> class CONTAINER>
void func2()
{
CONTAINER<T,ALLOCATOR> container;
container.push_back( T() );
}
int main()
{
func2<std::vector<bool>>();
}
This is useful when you need to extract the template parameters of a class template which you have passed as template parameter.
Checkout this question for more info.
On the other hand, as chris noticed in his answer, in your case its easier to pass a type parameter and suppose that type has a member type value_type
, which is used to get the type of the elements of the container.
Upvotes: 2
Reputation: 61910
From your calls, I suspect you just want something like this (I'll make the code as close to what you have as possible and keep it C++03):
template<typename T>
void func1() {
T t;
t.push_back(typename T::value_type());
}
typename
expects a type - any type - and that's what it gets with vector<int>
, list<float>
, etc. On the other hand, vector
by itself is just a template, not a type on its own. That's when you would need template<template<...> class>
syntax.
Do note, however, that trying to group containers like this often won't work because not every container supports the same operations as others. If you need an interface like this, you'll have to differentiate sequence containers, associative containers, etc.
Upvotes: 2
Reputation: 267
first of all new
will return a pointer, so the containers will not accept this, change that line, also you could do the following:
template<typename Container, typename T >
void func1() {
Container c;
c.push_back(T());
}
and in the main function:
func1<std::vector<int>, int >();
Upvotes: 1