Alex Vinokur said:
* Alex Vinokur:
If the callback is only called during initialization I don't see why not.
Otherwise, if you can specify the int argument to the callback, then use a
std::map as the global, not just a single pointer, and the int argument as key
to the map.
I tried to do something like this. [snip]
Otherwise, if you can't specify the argument then it seems the API you're
using supports only a single callback which can be called at any time, and you
then have to decide whether you want just a single object to receive the call
or whether to distribute it to all objects, or what.
[snip]
I have resolved the problem in my _specific_ conditions.
Here is an erroneous program that doesn't take into account any _specific_ conditions.
------ erroneous program ------
struct BaseCaller
{
virtual void callback (long) = 0;
virtual ~BaseCaller() {}
};
struct Caller1 : public BaseCaller
{
void callback (long)
{
// Stuff
}
};
struct Caller2 : public BaseCaller
{
void callback (long)
{
// Stuff
}
};
struct Worker
{
void (*the_callback) (long); // We can't change this prototype
};
#define RED 1
#define BLUE 2
#define GREEN 3
struct Called
{
const int type_; // RED, BLUE or GREEN
Worker Worker_;
Called (int type_i, BaseCaller* ptr_i) : type_ (type_i)
{
Worker_.the_callback = ptr_i->callback; // Erroneous
}
};
int main ()
{
Caller1 caller1;
Caller2 caller2;
Called called1 (RED, &caller1);
Called called2 (BLUE, &caller2);
Called called3 (GREEN, &caller1);
return 0;
}
-------------------------------
Here are _specific_ conditions:
1. Maximum three types of Called-object can exist simultaneously.
2. No type of Called-object (RED, BLUE, GREEN) can exist more than once.
Here is a valid program.
------ valid program ------
#include <cassert>
#include <map>
using namespace std;
struct BaseCaller
{
virtual void callback (long) = 0;
virtual ~BaseCaller() {}
};
struct Caller1 : public BaseCaller
{
void callback (long)
{
// Stuff
}
};
struct Caller2 : public BaseCaller
{
void callback (long)
{
// Stuff
}
};
struct Worker
{
void (*the_callback) (long); // We can't change this prototype
};
#define RED 1
#define BLUE 2
#define GREEN 3
struct Called
{
static map<int, BaseCaller*> types_s;
const int type_; // RED, BLUE or GREEN
Worker Worker_;
static void red_callback_s (long arg_i)
{
types_s[RED]->callback(arg_i);
}
static void blue_callback_s (long arg_i)
{
types_s[BLUE]->callback(arg_i);
}
static void green_callback_s (long arg_i)
{
types_s[GREEN]->callback(arg_i);
}
Called (int type_i, BaseCaller* ptr_i) : type_ (type_i)
{
assert (types_s.count(type_) == 0); // In actual program to be replaced by some check
types_s[type_] = ptr_i;
switch (type_)
{
case RED:
Worker_.the_callback = red_callback_s;
break;
case BLUE:
Worker_.the_callback = blue_callback_s;
break;
case GREEN:
Worker_.the_callback = green_callback_s;
break;
default:
assert(0);
break;
}
}
};
map<int, BaseCaller*> Called::types_s;
int main ()
{
Caller1 caller1;
Caller2 caller2;
Called called1 (RED, &caller1);
Called called2 (BLUE, &caller2);
Called called3 (GREEN, &caller1);
return 0;
}