wrote in news:11*********************@g14g2000cwa.googlegro ups.com in
comp.lang.c++:
Rob Williscroft wrote: template < template <typename> class GenericClient >
class ServerClass
{
//...
}
Ok, this one is not easy.
The server-class template assumes that you pass a class which is again
a template as parameter. Right?
The paramiter is template-template paramiter and it must
be passed a class-template that takes one type paramiter.
std::vector< GenericClient< ServerClass > > (
10, GenericClient< ServerClass >(this)
I think this is the tricky part. The compiler knows that the
GenericClient awaits another class as parameter. If we would write this
outside of our template we would have a circular (or recursive)
dependency. But now we can pass the template class for our client as
parameter and thus avoid the circular dependency.
Well the bit you quoted is inside a constructor, templates and there
members are only instantiated when they're needed. Before it
instantiates the constructor it will instantiate the class to do that
it needs to instantiate the data member:
std::vector< GenericClient<ServerClass> > clients;
to do that it may need to instantiate:
GenericClient<ServerClass>
Fortunatly this can be done without knowing anything about
ServerClass as neither:
ClientSubclass< ServerClass > or
ClientSubclass< ServerSubClass >
require knowing anything about ServerClass or ServerSubClass
as they only use a pointers to a ServerClass.
The terminoligy used to refere to this is "ClientSubclass can
be instantiated with an incomplete type", ServerSubClass (and
ServerClass) being the incomplete (because they're currently
being instatiated) types.
Also I noticed that the code I posted may not do precisley
what you wanted, as the ServerSubClass contains a std::vector
of ClientSubClass< ServerClass > where as IIUC you wanted
a vector of ClientSubClass< ServerSubClass >.
Here's the fixed code, it has an extra paramiter to ServerClass
to feed in the sub-class type and a static_cast to cast from the
base type to the derived type:
#include <iostream>
#include <ostream>
#include <vector>
template < template <typename> class GenericClient, typename Server >
class ServerClass
{
public:
ServerClass() :
clients(
std::vector< GenericClient< Server > > (
10, GenericClient< Server >(static_cast< Server *>( this ) )
)
)
{
}
void print()
{
std::size_t i, len = clients.size();
for ( i =0; i < len; ++i )
{
clients[i].print();
}
}
protected:
std::vector< GenericClient< Server > > clients;
int foo;
};
template < template <typename> class GenericClient >
class ServerSubclass :
public ServerClass<GenericClient, ServerSubclass< GenericClient > >
{
public:
ServerSubclass() {}
protected:
int bar;
};
template <typename GenericServer>
class ClientClass
{
public:
ClientClass() : server(NULL) {}
ClientClass(GenericServer *aServer) { server = aServer; }
virtual void print() {}
protected:
GenericServer *server;
};
template <typename GenericServer>
class ClientSubclass : public ClientClass< GenericServer >
{
public:
ClientSubclass() {}
ClientSubclass(GenericServer *aServer) :
ClientClass< GenericServer >(aServer), bla( 0 )
{
}
ClientSubclass( ClientSubclass const &rhs ) : bla( ++rhs.bla )
{
}
virtual void print() { std::cout << bla << '\n'; }
protected:
mutable int bla;
};
ServerSubclass< ClientSubclass > server;
int main()
{
server.print();
}
Rob.
--
http://www.victim-prime.dsl.pipex.com/