Is there a way so that I can write code as the follows:
IConnection<Socket> s{Socket{...}}; // statically
Connection* c = new Socket{...}; //dynamically
// a heterogeneous list that require dynamically dispatch /existential type/ type erase
List<Connection*> l { new Socket{...}
, new MockSock{...}, new LocalDataBase{...}, ...}
I tried to implement class suitable for both dynamic and static polymorphism on a need-to-erase basis, i.e. only use dynamic polymorphism if i have to (heterogeneous list, e.g.). I write following code
class Connection {
public:
Connection& operator=(Connection& c) = delete;
Connection(Connection& c) = delete;
Connection& operator=(Connection&& c) = delete;
Connection(Connection&& c) = delete;
virtual ~Connection() = 0;
virtual string Recv() = 0;
}
template<typename T>
class IConnection : Connection{
public:
inline T* dispatch(){
return static_cast<T*>(this);
}
virtual string Recv() override{
return dispatch()->Recv();
}
...
}
However, if i am to implement class Socket :IConnection<Socket>, then Recv() in class Socket would still be a dynamic dispatch.
Your problem starts when you inherit from
Connection. You definedConnectionas an abstract class, meaning the compiler will generate a vtable and all those fun toys.Things that expect a
Connection*expect the vtable and such.But at the same time, you want the
Connectioninterface to sometimes be static. Which means the callers will have to change the way they call stuff. But those are two very distinct types with two very different calling conventions.You can't have both under the same interface.\
What you can do is a templated
Connectionclass that receives a type and assumes that that type has the functions you expect and calls them in functions with the same name. You won't be able to pass it to stuff that expectsConnection*generically, but it might still suit your needs.This way, if
foois an object that implements some interface that requiresrecv(),Connection<foo>will use the vtable and you'll have dynamic dispatch. If you construct aConnection<bar>where bar is a plain class that happens to have arecv()method, it will still work, and you'll get static dispatch.