?

Log in

Abusing c++ - A Slave to Variance [entries|archive|friends|userinfo]
Andrew

[ website | My Website ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Links
[Links:| My Poker Blog PokerStove: A Poker Calculator European Vacation Current Fiction Current Non-Fiction ]

Abusing c++ [Feb. 27th, 2013|11:29 pm]
Andrew
Playing around with sample code for the purposes of (1) cleaning up code (2) showing off my guru skills. Not sure that (1) is sufficiently compelling to introduce (2) into the codebase.



#include <iostream>
#include <string>
#include <map>

using namespace std;

class delegate
{
public:
    delegate()
    {
        m_dispatch["hola"] = &delegate::hello;
        m_dispatch["adios"] = &delegate::goodbye;
    }

    void dispatch(string message, string data)
    {
        if (m_dispatch.find(message) != m_dispatch.end())
            (this->*m_dispatch[message])(data);
        else
            cout << "could not find: " << message << " " << data << endl;
    }

private:
    void goodbye(string in)
    {
        cout << "goodbye: " << in << endl;
    }

    void hello(string in)
    {
        cout << "hello: " << in << endl;
    }

    typedef void (delegate::* member_function)(string) ;

    map<string,member_function> m_dispatch;
};

int main(void)
{
    delegate dispatcher;
    dispatcher.dispatch("hola", "world");
    dispatcher.dispatch("adios", "cruel world");
    dispatcher.dispatch("lost", "world");
}
LinkReply

Comments:
[User Picture]From: markgritter
2013-02-28 08:50 am (UTC)
Not the worst abuse of member function pointers I've seen (or committed.)

"using namespace std", though? C'mon.

(Reply) (Thread)
[User Picture]From: prock
2013-02-28 03:31 pm (UTC)
"using namespace std", though? C'mon.

In cpp files, pretty much any time I feel like it. In header files, never.

I suppose I could have been pendantic about it and wrote "using std::cout", etc.

Edited at 2013-02-28 03:31 pm (UTC)
(Reply) (Parent) (Thread)
[User Picture]From: freelikebeer
2013-02-28 04:18 pm (UTC)
This is interesting for me. For lightweight behaviors, it makes sense to me to use function pointers, which would mean that std::map is a member of the delegate class. When do you decide to move the map outside of the behavioral class and create a dispatch_selector class that you initialize with a set of behavioral classes [say, all descended from an abstract base class]?
(Reply) (Parent) (Thread)
[User Picture]From: prock
2013-02-28 05:32 pm (UTC)
Typing is hard!

Which do you choose?

int color;
std::string color;
typedef std::string color_t;
enum color { ... };
class Color;
class Color : public Wavelength { ... };

etc...

It will all depend on the surrounding idioms, and how that concept needs to be reused across the code base.

For the case of dispatching, you might use a long string of if/else (which is what the code does that I'm working on), switch statements, virtual methods, function pointers, function objects, etc. Again, dominant idioms and practical considerations will be a factor in the decision. There's a fine balance between too little modularity, and too much, and types can play havoc with that. If you create lots of new types instead of using built in types, then you're creating more coupling, both conceptual and code level. If you have no types, then you don't get compile time type validation, and have to manually convert/serialize/etc every time you want to use the type.

Edited at 2013-02-28 05:50 pm (UTC)
(Reply) (Parent) (Thread)
[User Picture]From: freelikebeer
2013-03-01 12:03 am (UTC)
It will all depend on the surrounding idioms, and how that concept needs to be reused across the code base.

I'm going to print that out and tape it in my cube.
(Reply) (Parent) (Thread)
[User Picture]From: adb_jaeger
2013-03-01 02:46 am (UTC)
That quote works better if you spell it "surrounding idiots".
(Reply) (Parent) (Thread)