2

Let's say I have a simple Server with a template which accepts a Client as it's template argument:

template<class T>
class Server<T>{
    Server(int port);
}

and a Client is defined something like this:

class Client{
    Client(Server<Client> *server, // <--
           int socket);
};

But I also want say, have the class User inherit from Client (class User : public Client), so I could do Server<User> instead of Server<Client>. class User obviously needs to pass Server<Client> as a parameter when constructing Client. However, with the current implementation this seems impossible.

How should I approach this problem?

1 Answer 1

4

What about this?

template<class T>
class Server<T>{
    Server(int port);
};

template<class Derived>
class Client {
    Client(Server<Derived> *server, int socket);
    virtual ~Client() {} // Base classes should have this
};

class User : public Client<User> {
};
Sign up to request clarification or add additional context in comments.

5 Comments

Required some refactoring of existing code, but this was essentially what I wanted. Great thanks!
Actually, the destructor would probably be better to be protected and non-virtual. This design almost certainly doesn't want people deleting instances of User through a Client<User> *.
@rstevens: because in order to even have a Client<User> pointer, they have to know that the object is in fact a User, not just some generic Client. So why wouldn't they just have a pointer to User? This pattern means that there is no common base class for all the different client "subclasses": Client<User1> and Client<User2> are unrelated. So runtime polymorphism is not appropriate. If the Client class template specified a non-template public base, ClientBase, then we'd be back to a common base class, and then sure, ClientBase could/should have a virtual destructor.
"why wouldn't they just have a pointer to User" - actually there is an answer to that, which is they might be doing something template-y themselves, and somehow be lumbered with the essentially useless Client<User> type as a template parameter more-or-less by accident. If this can't be fixed, and they absolutely have to delete through that type because they can't cast to User*, then I suppose you might let them. In general, though, I write C++ with runtime polymorphism not supported by default. Gives you more freedom to do useful C++-ish things, like using standard containers of values.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.