mardi 22 septembre 2020

C++/C++11 typedef on a templated function with member usage

I have two functions which need to be exposed by the class and they look like this (more will follow):

void print_a(std::string s);
void print_b(std::string s, int val);

"Under the hood" they are doing the same exact thing namely doing a lookup in a map and passing the call parameters to the function pointer retrieved by the map:

#include <stdint.h>
#include <iostream>
#include <string>
#include <map>

class Thing{
private:

    void do_a(){
        std::cout << "hello";
    }
    //there might be also a method do_a_extended() which has a different key in the map

    void do_b(int age){
        std::cout << "my age is " << age;
    }


    typedef void (Thing::*do_stuff_a)();
    typedef void (Thing::*do_stuff_b)(int);

    std::map<std::string, do_stuff_a> a_table;
    std::map<std::string, do_stuff_b> b_table;

public:
    
    void print_a(std::string s){
        do_stuff_a handler = a_table[s];
        if(handler){
            (this->*handler)();
        }
    }

    void print_b(std::string s, int val){
        do_stuff_b handler = b_table[s];
        if(handler){
            (this->*handler)(val);
        }
    }

};

I dislike the fact that there is a lot of boilerplate code involved. I wonder if its possible to pass a member into template so I can this:

class Thing{
private:

    void do_a(){
        std::cout << "hello";
    }

    void do_b(int age){
        std::cout << "my age is " << age;
    }


    typedef void (Thing::*do_stuff_a)();
    typedef void (Thing::*do_stuff_b)(int);

    std::map<std::string, do_stuff_a> a_table;
    std::map<std::string, do_stuff_b> b_table;


    template<<MAP_MEMBER>,typename ... PP>
    void print_x(std::string s, PP &&... pp){
        auto handler = <MAP_MEMBER>[s];
        if(handler){
            (this->*handler)(std::forward<PP>(pp) ...);
        }
    }
public:
    
    typedef decltype(print_x<a_table>) print_a;
    typedef decltype(print_x<b_table>) print_b;

};

Any ideas on how to get rid of boilerplate is appreciated.

Aucun commentaire:

Enregistrer un commentaire