Click to See Complete Forum and Search --> : Templates: why can't I do this?


jfaust
July 22nd, 2002, 11:42 AM
#include <list>

template<class C, class T>
class MyContainer
{
private:
C<T> m_container;
};

class A
{
};

int main()
{
MyContainer<std::list, A*> container();

return 0;
}


It doesn't like the line "C<T> m_container;" and gives me the error "error C2059: syntax error : '<'".


Jeff

Paul McKenzie
July 22nd, 2002, 12:33 PM
std::list is not a type, it is a template. The following code works correctly.

#include <list>

template<typename C>
class MyContainer
{
private:
C m_container;
};

class A
{
};

int main()
{
MyContainer<std::list<A*> > container(); // Remember to put a space between the "> >"

return 0;
}

Regards,

Paul McKenzie

jfaust
July 22nd, 2002, 12:40 PM
Paul,

I was just about to post the same thing, with one additional typedef:


#include <list>
#include <set>

template<class C>
class MyContainer
{
public:
typedef C::value_type value_type;
private:
C m_container;
};

class A
{
};

int main()
{
MyContainer<std::list<A*> > myList();
MyContainer<std::set<A*> > mySet();

return 0;
}



With the typedef for value_type defined in the std:: container , it's possible to return items in the container.

Thanks for the reply. I've found a good solution. However, I'm still not clear on why my original post does not work.

Jeff

Paul McKenzie
July 22nd, 2002, 12:53 PM
The reason why it doesn't work is that a template argument is looking for a concrete type, for example, int, double, char, std::string, std::list<int>, std::list<A*>, etc.

std::list is not a type. It is a template class that defines a family of types. However, std::list<int> is a concrete type, since you are describing a list of integers.

And BTW, your int main() function now has declared two functions, not instances:

int main()
{
MyContainer<std::list<A*> > myList(); // Function returning a MyContainer<std::list<A*> >
MyContainer<std::set<A*> > mySet(); // Function returning a MyContainer<std::set<A*> >

MyContainer<std::list<A*> > myList2; // Instance of MyContainer<std::list<A*> >
MyContainer<std::set<A*> > mySet2; // Instance of MyContainer<std::set<A*> >
}

Regards,

Paul McKenzie

jfaust
July 22nd, 2002, 12:57 PM
It's starting to make sense. Thanks for the reply.

And yes, I noticed my function declarations. Well, I noticed them as soon as I tried to use them ;).

Jeff

Graham
July 22nd, 2002, 04:11 PM
Doesn't ANSI C++ allow

template<template <class> class C, class T>
class MyContainer
{
// blah, blah

C<T> m_container;
};

int main()
{
MyContainer<std::list, int> mc;
}

Of course, VC++ doesn't support that syntax, but who's surprised by that?

jfaust
July 22nd, 2002, 04:22 PM
Can somebody try this on a better compiler?

Jeff

Graham
July 23rd, 2002, 03:31 AM
This compiles with Comeau:

#include <list>

template<template <class, class> class C, class T>
class MyContainer
{
// blah, blah

C<T, std::allocator<T> > m_container;
};

int main()
{
MyContainer<std::list, int> mc;
}

Note that I had to change it a bit because list actually has two template parameters.

Paul McKenzie
July 23rd, 2002, 05:26 AM
Thanks Graham,

I knew that there are now template-template parameters, but didn't go to Comeau to try out the new syntax.

Regards,

Paul McKenzie