I have a little inheritance/template problem. I'm trying to create an interface IBinding which is implemented by a TcpClient and a TcpServer (there will be 2-3 different TcpServers which differ only in the type of Stream(Socket abstraction) they generate after accepting a connection request.
Here is a simplified example:
Interface:
struct IBinding
{
virtual ~IBinding() {}
virtual void bind(const std::string endpoint) = 0;
virtual void terminate() = 0;
};
typedef std::shared_ptr<IBinding> TBindingPtr;
Header:
#include "IBinding.h"
class TcpServer : public IBinding
{
public:
TcpServer();
~TcpServer();
virtual void bind(const std::string endpoint);
virtual void terminate();
};
Implementation:
#include "TcpServer.h"
#include "StreamTypeA.h"
#include "StreamTypeB.h"
TcpServer::TcpServer() { }
TcpServer::~TcpServer() { }
void TcpServer::terminate() { }
void TcpServer::bind(const std::string endpointStr)
{
auto stream = std::make_shared<StreamTypeA>(); // Here I need to use different types depending on the server implementation
}
Now, I want to create two instances of a TcpServer and call .bind() on them, but they should create different types of Streams.
a) As far as I understand, it's not possible to pass a Type to the bind() method as an argument in c++
b) Trying to define the bind method templated also doesn't work, because it is virtual
template<class TSocket>
virtual void bind(const std::string endpoint);
c) I could probably just create two different implementations of the TcpServer
Is there another way? Isn't there a way to do it with templates?
No. Template functions are inherently incompatible with virtual dispatch. You cannot override them. They can be name hidden, but that won't help you probably. So you either need to provide virtual functions for each stream type you will use, or create an abstraction for stream types that can be used at the IBinding level.
Related
Suppose i have a socket class:
class Socket{
public:
... Some Code ...
Socket(int type){
isServer = type;
//some code
}
virtual void Send(string s);
virtual void Send(string s, int clientID);
... Some Code ...
private:
int isServer;
};
This is to be used both as a server and client.
Now I need to have 2 Derived classes:
class ClientSocket : public Socket{
public:
... Some Code ...
};
class ServerSocket : public Socket{
public:
... Some Code ...
};
What I want is that ClientSocket will only have access to Send(string) and server socket will only have access to Send(string, int)
I checked some other answer:
https://stackoverflow.com/a/20997981/14911094
And that has a good idea of not using inheritance at all rather just encapsulate(Have a socket instance in server). But I want to know whether this can be done using Inheritance.
There is not absoulte way to doing such thing.
But here my idea:
create two class(like interface):
first class is server socket sender:
Class ServerSocketSender {
public:
virtual void Send(string s, int clientID);
}
second class is client socket sender:
Class ClientSocketSender {
public:
virtual void Send(string s);
}
due to interface segregation principle i recommend you to do such thing it is not wise choice to combine two send method in one class and enable desire method in desire class.
another trick that i saw many times but i dont know exactly if it's work in your case or not is something called SFINAE. with this trick i think you can achieve same thing but due to complexity i not recommend this approach.
I am creating a simple event system where multiple listeners can be notified on a specific topic and when an event is fired, it can pass a generic payload to the event, and the listeners will match the format of the fired event. However, because it's not possible to use templates on a virtual function, how else can I achieve this?
class AEventListener
{
public:
template<class T>
struct PayloadObject {
T obj;
};
explicit AEventListener();
virtual ~AEventListener();
//error here because T is undefined. Each PayloadObject may have a different type
virtual void notify(vector<shared_ptr<PayloadObject<T>>> payload) = 0;
};
The notify method is called when an event topic has a listener subscribed, but I want a generic way of just passing a load of random objects to the listener.
For example
fireEvent("test.topic", Payload { 0, "hello", 123 });
//...
listener.notify(payload);
How would I go about this in C++?
I have managed to get around this, although I don't think this is the best way and could slow down performance.
template<class T>
struct PayloadObject : public APayloadObject {
T obj;
PayloadObject(T obj) {
this->obj = obj;
}
~PayloadObject() override {
};
};
struct APayloadObject {
virtual ~APayloadObject();
};
Firing:
vector<shared_ptr<APayloadObject>> payload;
payload.push_back(shared_ptr<PayloadObject<int>>(new PayloadObject<int>(5))); //payload[0] = int - 5
Events::fire(EventKeys::DISCONNECTION_EVENT, payload);
Notifying:
shared_ptr<PayloadObject<int>> number = dynamic_pointer_cast<PayloadObject<int>>(payload[0]);
int id = number.get()->obj; //payload[0] = int - 5
One simple approach is to come up with a common base or common interface for the Payload objects. So that they are not a template class.
struct Payload {
virtual ~Payload() = default;
virtual std::string foo() const;
virtual std::string bar() const;
};
Another way is to use a variant type for the payload objects:
using Message_t = boost::variant<A, B, C>;
and then make AEventListener take the Message_t type so that it doesn't require the member function to be a template.
class AEventListener
{
public:
virtual ~AEventListener();
virtual void notify(std::vector<Message_t> payload) = 0;
};
In C++17 you could use std::variant for this instead of boost.
Yet another way is to skip using a variant, and just make it so that the Listener must implement three different functions, one for each type:
class AEventListener
{
public:
virtual ~AEventListener();
virtual void notifyA(A payload) = 0;
virtual void notifyB(B payload) = 0;
virtual void notifyC(C payload) = 0;
};
More generally, it is pretty difficult in C++ to make a concept like "Function object that is callable with any particular type of arguments". This is in part because... it is not very useful, there is not much that you can do generically with data of ANY type that you can assume nothing about.
So I would suggest that you think hard about refining your Event Listener concept, and make more concrete what it is that objects of this type are ACTUALLY supposed to be required to do.
We are designing a new system where we have created interfaces for most of our classes so that we can create mocks (google mocks) for them for unit testing. As a result, all the functions are virtual but the issue is that I am often running into template virtual function issue due to this. I have seen some examples on how to do multi dispatch but they all seem to be using some variation of templates, it doesn't seem straightforward. So does it mean that my entire codebase will now end up with templates making it difficult to read/use and debug?
Or am I not designing good interfaces. Here is a simple example where I am writing an interface for a message queue.
Class IMessageQueue {
Public:
Virtual int send(const T & value); // I can't do this but this is exactly what I want to do, as send should be able to send any type
};
Class MessageQueue : public IMessageQueue {
Public:
Virtual int send(const T & value) { ... }
};
Class MockMQ : public IMessageQueue {
Public:
Virtual int send(const T & value) {
// mock implementation
}
};
How do I get around this problem? This is just one example but I run into lots of these type of issues due to interface based programming.
It depends if you need your IMessageQueue to dispatch specific unknown type or any type. That's not the same thing.
A specific unknown type can be managed by
template<typename T>
class IMessageQueue {
public:
virtual int send(const T& value);
}
So that you can have your IMessageQueue<MyMessage> and IMessageQueue<OtherMessage>.
If, instead, you need to be able to send any type with the same type of message queue then your option is to declare a specific interface common to all messages as in
class Message
{
protected:
Message() : { .. }
};
class MyMessage : public Message
{
..
};
class MessageQueue
{
public:
void send(const Message& message);
};
class Connection
{
public:
typedef boost::shared_ptr<Connection> pointer;
static pointer create(boost::asio::io_service& io_service){return pointer(new Connection(io_service));}
explicit Connection(boost::asio::io_service& io_service);
virtual ~Connection();
boost::asio::ip::tcp::socket& socket();
-->>>virtual void OnConnected()=0;
void Send(uint8_t* buffer, int length);
bool Receive();
private:
void handler(const boost::system::error_code& error, std::size_t bytes_transferred );
boost::asio::ip::tcp::socket socket_;
};
when am trying to use virtual void OnConnected()=0; it gives me this stupid error idk whats wrong!!!
1 IntelliSense: object of abstract class type "Connection" is not allowed: d:\c++\ugs\accountserver\connection.h 17
whats wrong and how can i fix it while in my old connection class it was working good!!
class Connection
{
public:
explicit Connection(int socket);
virtual ~Connection();
virtual void OnConnected() =0;
virtual int Send(uint8_t* buffer, int length);
bool Receive();
int getSocket() const;
void Disconnect();
protected:
virtual void OnReceived(uint8_t* buffer, int len) = 0;
private:
int m_socket;
bool disconnecting;
};
so what am missing here!!
You have not provided a definition for OnReceived, it is therefore a pure virtual (abstract) method and the class an abstract class. You cannot instantiate an object of an abstract class. To use the method OnReceived you have to, well, provide an implementation for it (what does it do at the moment? nothing). Abstract classes are intended to be subclassed by concrete implementations which then provide implementations for the pure virtual methods.
EDIT: The part new Connection(io_service) does not work for the above mentioned reason: you cannot create an object of a class, that has pure virtual functions (those declarations ending with = 0;). You need to subclass Connection and provide implementations for those methods (like OnConnected). Your old class didn't have that problem. It had pure virtual methods, but you have not tried to instantiate it. If you still don't see the error, I suggest you to consult some material on object-orientation in C++, especially virtual and pure virtual methods.
You have decided to make Connection abstract, but then attempted to instantiate it. Which did you mean to do?
You an use it, but not until it is implemented in some derived class.
You cannot create objects of abstract classes, because not all functions are implemented.
I have a base class which implements the following:
struct Consumer
{
template <typename T>
void callback(T msg) { /*null implementation */ }
};
I then have a class implement this:
struct Client : public Consumer
{
void callback(Msg1 msg);
void callback(Msg2 msg);
void callback(Msg3 msg);
};
The issue is I have a container of Client objects treated as Consumer* and I can't think of a way to get these Consumer objects to call the derived functions. My intended functionality is to have multiple Clients each of which implement an overloaded function for each Msg class that means something to them and the rest of the calls simply call the null implementation in the base class
Any thoughts how I can get the derived class to be called? Right now I need to implement every overloaded function in Consumer and mark them as virtual.
Cheers,
Graeme
If you really don't want to use virtual functions (this seems to be a perfect use case for them actually, but I don't know about your message classes), you can use the CRTP:
template <typename U>
struct Consumer
{
template <typename T>
void callback(T msg)
{ static_cast<U*>(this)->callback(msg); }
};
struct Client : Consumer<Client>
{
void callback(Msg1 msg);
void callback(Msg2 msg);
void callback(Msg3 msg);
};
The problem, of course, is that you cannot store Consumer objects in a container any more. Since everything is compile time, the actual type of the client must be stored alongside the consumer object for the compiler to call the right callback function. Virtual functions allow you to wait until runtime for this...
Is there a reason not to have Msg classes polymorphic and use standard virtual functions (other than "I have to rewrite all the code and I cannot") ?
EDIT If your concern is about message classes, why not use something like that, assuming message classes implement a DoSomething member function: (this technique is known as Type Erasure)
struct AnyMsg
{
template <typename Msg>
AnyMsg(Msg x) : impl(newImpl(x)) {}
void DoSomething() { impl->DoSomething(); }
private:
struct Impl
{
virtual ~Impl() {}
virtual void DoSomething() = 0;
};
// Probably better is std::unique_ptr if you have
// C++0x. Or `boost::scoped_ptr`, but you have to
// provide copy constructors yourself.
boost::shared_ptr<Impl> impl;
template <typename Msg>
Impl* newImpl(Msg m)
{
class C : public Impl
{
void DoSomething() { x.DoSomething(); }
Msg x;
public:
C(Msg x) : x(x) {}
};
return new C(m);
}
};
You can customize the behavior of newImpl to get what you want (eg. default actions if there is no DoSomething member function in the message class, specialization for some message classes or anything else). This way, you implement Msg classes like you would have done with your template solution, and you have a unique facade that you can pass to the virtual functions in your client classes.
If the Message classes are going to be very different, and client classes may react differently to them, and you are going to have a lot of message classes, this begins to smell. Or perhaps you have a candidate for the ugly and scary Visitor pattern.
Since you don't want to use virtual methods, the compiler would have to know statically (i.e. at compile time) which function to call. If you have different client objects in your container, there is now way the compiler could possibly know this. So I think there's no solution to your problem without using virtual methods (which are btw. exactly designed for this kind of situations...).
Of course you could alternatively using some switch statements for manually deriving the concrete type, but this is neither elegant nor efficient (and you would have to hardcode all possible client types ...)
EDIT
Personally, I'd implement some base message class containing a type code and implement a switch statement in the client class to handle different message types like:
struct MsgBase {
int type;
};
struct Consumer {
virtual void callback(MsgBase msg) { };
};
struct Client : public Consumer {
void callback(MsgBase msg) {
switch (msg.type) {
case MSGTYPE1:
callback((Msg1)msg);
break;
case MSGTYPE2:
callback((Msg2)msg);
break;
// ...
}
}
void callback(Msg1 msg) { /* ... */ }
void callback(Msg2 msg) { /* ... */ }
};
You could also make MsgBase polymorphic (e.g. virtual destructor) and use typeid to differentiate (more elegant but slightly less efficient ...)
struct Client : public Consumer {
void callback(MsgBase* msg) {
if (typeid(*msg) == typeof(Msg1))
callback(static_cast<Msg1*>(msg));
else if (typeid(*msg) == typeof(Msg2))
callback(static_cast<Msg2*>(msg));
}
// ...
};
This is always a difficult situation to make totally extensible, as is the case usually with the Visitor pattern.
You end up needing up to V*T implementations where V is the number of "visitors" and T is the number of types being visited and will probably end up having to use a mixture of visitor and class factory pattern.
visitors here would be your consumers
class factory would be used for the message types.
and your best way to make it totally extensible is to create new function "objects" for message/consumer pairs and a bit of double-dispatch to ensure the right one gets called.
In your case you have different messages come in and then you give them to your consumers who might handle them? So each message should have an identifiable "type" and your consumer
should look up this type in a table to create a handler for it.
You can have one handler per type per consumer class.