Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

a router for websocket messages, is there anything wrong with this implementation



  • I've built a router that is similar in syntax to laravel's router
    I know "get" and "post" will sound just like http, but I'm using them for convenience.
    here is the implementation:
    router.h

    #ifndef ROUTER_H
    #define ROUTER_H
    
    #include "message.h"
    class CNTRLR{}; //MSVC will throw C2440 when using reinterpret_cast with undefined classes
    
    using MemberCallback = void (CNTRLR::*)(Message &);
    
    struct MemberCallbackInfo
    {
        CNTRLR *instance;
        MemberCallback ptr;
    };
    
    typedef QMap<QString,MemberCallbackInfo> MemberCallbacks;
    
    class Router
    {
    public:
        explicit Router();
        void route(Message &message);
    
        template <class T> static void registerRoute(MemberCallbacks *callBacks,
        const QString& action,
        T *instance, void (T::*ptr)(Message &)){MemberCallbackInfo obj={reinterpret_cast<CNTRLR *>(instance),
        reinterpret_cast<MemberCallback>(ptr)};
        callBacks->insert(action, obj);}
        template <class T> static void get   (const QString& action, T *instance, void (T::*ptr)(Message &)){registerRoute(&getRoutes,action,instance,ptr);}
        template <class T> static void post  (const QString& action, T *instance, void (T::*ptr)(Message &)){registerRoute(&postRoutes,action,instance,ptr);}
    
    private:
        static MemberCallbacks getRoutes;
        static MemberCallbacks postRoutes;
    
    };
    
    typedef Router Route;
    
    #endif // ROUTER_H
    

    router.cpp

    #include "router.h"
    MemberCallbacks Router::getRoutes;
    MemberCallbacks Router::postRoutes;
    Router::Router()
    {
    
    }
    
    void Router::route(Message &message)
    {
        if(message.method()=="GET")
        {
            MemberCallbackInfo cb= getRoutes.value(message.action());
            (cb.instance->*cb.ptr)(message);
        }
        else if(message.method()=="POST")
        {
            MemberCallbackInfo cb= postRoutes.value(message.action());
            (cb.instance->*cb.ptr)(message);
        }
    }
    

    now if I want to route something I just have to type something like this from anywhere I want in the app

    Route::post("user/auth", this, &AuthController::authenticate);
    

    I've used a tricky way to store member function pointers and I'm not sure if it's type safe
    I used template functions so that I can make sure that the instance and the member function pointer are of the same class,
    I'm storing the info in a struct called "MemberCallbackInfo".

    class CNTRLR is just a dummy class.

    according to the Standard (section 5.2.10/9), you can use reinterpret_cast to store a member function for one class inside a member function pointer for an unrelated class,
    and that is what I did with the dummy class.

    is there a more elegant way(like utilizing Qt's signals,slots and Qt's metaobject system) to implement such router while keeping the same routing syntax above ?


Log in to reply