D
Default User
I'm not sure how well that subject captured the topic. Anyway, this is a
branching from my previous topic "Fun with member-function pointers".
The general problem is that we have a number of "drivers" for instruments.
These are essentially an abstraction layer than translates control messages
from higher-level modules into something the particular hardware can
understand. The API for this is a system of operation codes and an
associated data word that has bits set or cleared for various options.
My current solution is to map the op codes to pointers to member functions
that handle the particular operation. There's also a requirement that each
driver be able to respond with a list of the supported op codes. The problem
is that it results in a lot of very similar code in each driver. I had
wanted to push down as much behavior as possible to the base class. My
initial thoughts (see other thread) look like they result in undefined
behavior, so no good.
Below is a small representation of the problem. It's not the real code
(which would be very large), so it's not necessary to suggest improvements
in layout or that sort of thing. Thoughts on attacking the general problem
would be welcome.
Brian
================= code =================
#include <iostream>
#include <map>
#define CALL_HANDLER(object,ptrToMember)((object).*(ptrToMember))
class tbase
{
public:
protected:
tbase()
{
}
virtual ~tbase()
{
}
};
class test : public tbase
{
public:
typedef int (test::*HandlerPtr)(int);
test() // sets up the map of handlers to op codes
{
handlers[0] = &test::H0;
handlers[4] = &test::H4;
}
virtual ~tbase()
{
}
virtual int H0(int data)
{
std::cout << "test::H0: " << data << "\n";
return data;
}
int H4(int data)
{
std::cout << "test::H4: " << data << "\n";
return data;
}
void write(int data, int code) // finds the handler and passes data
{
std::map<int, HandlerPtr>::iterator it;
it = handlers.find(code);
if (it != handlers.end())
{
// Found, call the function pointer
CALL_HANDLER(*this, it->second)(data);
}
else // unhandled code
{
// error handling
}
}
void list() // just prints supported op codes
{
std::map<int, HandlerPtr>::iterator it = handlers.begin();
std::cout << "Supported Op codes:\n";
while (it != handlers.end())
{
std::cout << it->first << "\n";
it++;
}
}
private:
std::map<int, HandlerPtr> handlers;
};
int main()
{
test t;
t.list();
t.write(123, 0);
t.write(456, 4);
return 0;
}
branching from my previous topic "Fun with member-function pointers".
The general problem is that we have a number of "drivers" for instruments.
These are essentially an abstraction layer than translates control messages
from higher-level modules into something the particular hardware can
understand. The API for this is a system of operation codes and an
associated data word that has bits set or cleared for various options.
My current solution is to map the op codes to pointers to member functions
that handle the particular operation. There's also a requirement that each
driver be able to respond with a list of the supported op codes. The problem
is that it results in a lot of very similar code in each driver. I had
wanted to push down as much behavior as possible to the base class. My
initial thoughts (see other thread) look like they result in undefined
behavior, so no good.
Below is a small representation of the problem. It's not the real code
(which would be very large), so it's not necessary to suggest improvements
in layout or that sort of thing. Thoughts on attacking the general problem
would be welcome.
Brian
================= code =================
#include <iostream>
#include <map>
#define CALL_HANDLER(object,ptrToMember)((object).*(ptrToMember))
class tbase
{
public:
protected:
tbase()
{
}
virtual ~tbase()
{
}
};
class test : public tbase
{
public:
typedef int (test::*HandlerPtr)(int);
test() // sets up the map of handlers to op codes
{
handlers[0] = &test::H0;
handlers[4] = &test::H4;
}
virtual ~tbase()
{
}
virtual int H0(int data)
{
std::cout << "test::H0: " << data << "\n";
return data;
}
int H4(int data)
{
std::cout << "test::H4: " << data << "\n";
return data;
}
void write(int data, int code) // finds the handler and passes data
{
std::map<int, HandlerPtr>::iterator it;
it = handlers.find(code);
if (it != handlers.end())
{
// Found, call the function pointer
CALL_HANDLER(*this, it->second)(data);
}
else // unhandled code
{
// error handling
}
}
void list() // just prints supported op codes
{
std::map<int, HandlerPtr>::iterator it = handlers.begin();
std::cout << "Supported Op codes:\n";
while (it != handlers.end())
{
std::cout << it->first << "\n";
it++;
}
}
private:
std::map<int, HandlerPtr> handlers;
};
int main()
{
test t;
t.list();
t.write(123, 0);
t.write(456, 4);
return 0;
}