473,385 Members | 1,912 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

How to make every derived class to return a different int

Hi all,

I'm facing this design problem.

I have a table which defines the behaviour of an Object in a given
state according to the type of event it is receiving.

So for each couple event,state I want I set in the table a different
handler.

My trivial implementation make use of defines (but I could have used
an enum as well).

So I have:
#define EVT_FOO 0
#define EVT_BAR 1
....
#define EVT_FOOBAR N

Then I define for each event a virtual GetType() which returns the
event type.

This is ugly and awkward, since everytime I add an event I have to
update the enum/list of defines, while I would like to be able to
automatically get a different integer for every derived class of
Event.

Mayeb I could get this result with some kind of run-time registration
mechanism.

I think this problem should be quite common, so I thought maybe
someone can suggest a better design than that which requires the
enum/defines list.

Regards.
Sep 22 '08 #1
16 2138
Stefano Sabatini wrote:
Hi all,

I'm facing this design problem.

I have a table which defines the behaviour of an Object in a given
state according to the type of event it is receiving.

So for each couple event,state I want I set in the table a different
handler.

My trivial implementation make use of defines (but I could have used
an enum as well).

So I have:
#define EVT_FOO 0
#define EVT_BAR 1
...
#define EVT_FOOBAR N

Then I define for each event a virtual GetType() which returns the
event type.

This is ugly and awkward, since everytime I add an event I have to
update the enum/list of defines, while I would like to be able to
automatically get a different integer for every derived class of
Event.

Mayeb I could get this result with some kind of run-time registration
mechanism.
What about something like this:
unsigned int
count ( void ) {
static unsigned int c = 0;
return ( c++ );
}

struct reg_base {

virtual
unsigned int get_id ( void ) = 0;

};

template < typename D >
class reg : public reg_base {

static unsigned int const id;

public:

unsigned int get_id ( void ) {
return ( id );
}

};

template < typename D >
unsigned int const reg<D>::id = count();
struct X : public reg<X{};
struct Y : public reg<Y{};

#include <iostream>

int main ( void ) {
X x;
Y y1;
Y y2;
reg_base * p = new Y ();

std::cout << "X " << x.get_id() << '\n';
std::cout << "Y " << y1.get_id() << '\n';
std::cout << "Y " << y2.get_id() << '\n';
std::cout << "Y " << p->get_id() << '\n';
}

You could also add a static method that yields the id of a type.

I think this problem should be quite common, so I thought maybe
someone can suggest a better design than that which requires the
enum/defines list.

Best

Kai-Uwe Bux

Sep 22 '08 #2
On 2008-09-22 16:14, Stefano Sabatini wrote:
Hi all,

I'm facing this design problem.

I have a table which defines the behaviour of an Object in a given
state according to the type of event it is receiving.

So for each couple event,state I want I set in the table a different
handler.

My trivial implementation make use of defines (but I could have used
an enum as well).

So I have:
#define EVT_FOO 0
#define EVT_BAR 1
...
#define EVT_FOOBAR N

Then I define for each event a virtual GetType() which returns the
event type.

This is ugly and awkward, since everytime I add an event I have to
update the enum/list of defines, while I would like to be able to
automatically get a different integer for every derived class of
Event.

Mayeb I could get this result with some kind of run-time registration
mechanism.
You could put a const int in the base-class and set it to the correct
value in the constructor of each event class.
I think this problem should be quite common, so I thought maybe
someone can suggest a better design than that which requires the
enum/defines list.
It seems like you have a problem with your design. If you want to use
the number to distinguish the different events and based on that perform
different actions perhaps you should consider overloading some function
for the different event types instead.

--
Erik Wikström
Sep 22 '08 #3
unsigned int
count ( void ) {
* static unsigned int c = 0;
* return ( c++ );

}

struct reg_base {

* virtual
* unsigned int get_id ( void ) = 0;

};

template < typename D >
class reg : public reg_base {

* static unsigned int const id;

public:

* unsigned int get_id ( void ) {
* * return ( id );
* }

};

template < typename D >
unsigned int const reg<D>::id = count();

struct X : public reg<X{};
struct Y : public reg<Y{};

#include <iostream>

int main ( void ) {
* X x;
* Y y1;
* Y y2;
* reg_base * p = new Y ();

* std::cout << "X " << x.get_id() << '\n';
* std::cout << "Y " << y1.get_id() << '\n';
* std::cout << "Y " << y2.get_id() << '\n';
* std::cout << "Y " << p->get_id() << '\n';

}
I think it's better to eliminate count function altogether and put the
count functionality into class/struct such as, in your case, reg_base.
struct counter{

static unsigned int count getId(return id++;)

private:
static unsigned int id;

};
unsigned int counter::id=0;
Or some cleaner variation of that. I don't like member-less function
in the code. At the very least, we ought to namespace it if we're to
have this function, given that it's short to use and easier to code
than an alternative I've just mentioned.
Sep 22 '08 #4
Stefano Sabatini wrote:
Hi all,

I'm facing this design problem.

I have a table which defines the behaviour of an Object in a given
state according to the type of event it is receiving.

So for each couple event,state I want I set in the table a different
handler.

My trivial implementation make use of defines (but I could have used
an enum as well).

So I have:
#define EVT_FOO 0
#define EVT_BAR 1
....
#define EVT_FOOBAR N

Then I define for each event a virtual GetType() which returns the
event type.
What are you doing with these event/state couples?
Could it be that what you need is multi-methods?
Have you looked into patterns? I suspect that there are much
better ways to achieve whatever you're trying to do.
This is ugly and awkward, since everytime I add an event I have to
update the enum/list of defines, while I would like to be able to
automatically get a different integer for every derived class of
Event.

Mayeb I could get this result with some kind of run-time registration
mechanism.
It seems a compile-time problem, but I don't see a way to do
this at compile-time except by using vendor-specific compiler
extensions. (ISTR VC having some macro that expands to different
integers for each usage.)
I think this problem should be quite common, so I thought maybe
someone can suggest a better design than that which requires the
enum/defines list.
I think so, too.
What are you trying to do with your event/state couples?

Schobi
Sep 22 '08 #5
puzzlecracker wrote:
>
>unsigned int
count ( void ) {
static unsigned int c = 0;
return ( c++ );

}

struct reg_base {

virtual
unsigned int get_id ( void ) = 0;

};

template < typename D >
class reg : public reg_base {

static unsigned int const id;

public:

unsigned int get_id ( void ) {
return ( id );
}

};

template < typename D >
unsigned int const reg<D>::id = count();

struct X : public reg<X{};
struct Y : public reg<Y{};

#include <iostream>

int main ( void ) {
X x;
Y y1;
Y y2;
reg_base * p = new Y ();

std::cout << "X " << x.get_id() << '\n';
std::cout << "Y " << y1.get_id() << '\n';
std::cout << "Y " << y2.get_id() << '\n';
std::cout << "Y " << p->get_id() << '\n';

}

I think it's better to eliminate count function altogether and put the
count functionality into class/struct such as, in your case, reg_base.
struct counter{

static unsigned int count getId(return id++;)

private:
static unsigned int id;

};
unsigned int counter::id=0;
Or some cleaner variation of that. I don't like member-less function
in the code. At the very least, we ought to namespace it if we're to
have this function, given that it's short to use and easier to code
than an alternative I've just mentioned.
Yup. Also, get_id() wasn't const. Here is a cleaner version:

class reg_base {
protected:

static
unsigned int
count ( void ) {
static unsigned int c = 0;
return ( c++ );
}

public:

virtual
unsigned int get_id ( void ) const = 0;

virtual
~reg_base ( void ) {}

};

template < typename D >
class reg : public reg_base {

static unsigned int const the_id;

public:

unsigned int get_id ( void ) const {
return ( the_id );
}

static
unsigned int id ( void ) {
return ( the_id );
}

virtual
~reg ( void ) {}

};

template < typename D >
unsigned int const reg<D>::the_id = reg<D>::reg_base::count();
struct X : public reg<X{};
struct Y : public reg<Y{};

#include <iostream>

int main ( void ) {
X x;
Y y1;
Y y2;
reg_base * px = new X ();
reg_base * py = new Y ();

std::cout << "X " << x.get_id() << '\n';
std::cout << "Y " << y1.get_id() << '\n';
std::cout << "Y " << y2.get_id() << '\n';

std::cout << "X " << px->get_id() << '\n';
std::cout << "Y " << py->get_id() << '\n';

std::cout << "X " << X::id() << '\n';
std::cout << "Y " << Y::id() << '\n';

delete ( px );
delete ( py );
}
Best

Kai-Uwe Bux
Sep 22 '08 #6
On 2008-09-22, Erik Wikström <Er***********@telia.comwrote:
On 2008-09-22 16:14, Stefano Sabatini wrote:
>Hi all,

I'm facing this design problem.

I have a table which defines the behaviour of an Object in a given
state according to the type of event it is receiving.

So for each couple event,state I want I set in the table a different
handler.

My trivial implementation make use of defines (but I could have used
an enum as well).

So I have:
#define EVT_FOO 0
#define EVT_BAR 1
...
#define EVT_FOOBAR N

Then I define for each event a virtual GetType() which returns the
event type.

This is ugly and awkward, since everytime I add an event I have to
update the enum/list of defines, while I would like to be able to
automatically get a different integer for every derived class of
Event.

Maybe I could get this result with some kind of run-time registration
mechanism.

You could put a const int in the base-class and set it to the correct
value in the constructor of each event class.
Yes I already do that, I have a m_Type const int field in the Event
object and a GetType() which returns this type, every GetType() is
redefined for each object (for example for each Event object), so that
every one returns a different value. The problem is that I have to
rely on the enum/defines already defined, while I would like to be
able to add a new event type without the need to redefine the
enums/defines.
>I think this problem should be quite common, so I thought maybe
someone can suggest a better design than that which requires the
enum/defines list.

It seems like you have a problem with your design. If you want to use
the number to distinguish the different events and based on that perform
different actions perhaps you should consider overloading some function
for the different event types instead.
Well in this case I need to redefine a different integer for every
object type, this because that index is used to access a table.
This table defines an handler to be called for each state/event
couple, that is for each event arrived I want to perform a different
action based on the state of the object.

Thanks for your help.

(I'll look at the other comments too soon).
Sep 23 '08 #7
On 2008-09-22, Hendrik Schober <sp******@gmx.dewrote:
Stefano Sabatini wrote:
>Hi all,

I'm facing this design problem.

I have a table which defines the behaviour of an Object in a given
state according to the type of event it is receiving.

So for each couple event,state I want I set in the table a different
handler.

My trivial implementation make use of defines (but I could have used
an enum as well).

So I have:
#define EVT_FOO 0
#define EVT_BAR 1
....
#define EVT_FOOBAR N

Then I define for each event a virtual GetType() which returns the
event type.

What are you doing with these event/state couples?
Could it be that what you need is multi-methods?
Have you looked into patterns? I suspect that there are much
better ways to achieve whatever you're trying to do.
Mmmh... do you mean something like this:
http://www.codeproject.com/KB/recipes/mmcppfcs.aspx
?

Yes I should know better patterns...
>This is ugly and awkward, since everytime I add an event I have to
update the enum/list of defines, while I would like to be able to
automatically get a different integer for every derived class of
Event.

Mayeb I could get this result with some kind of run-time registration
mechanism.

It seems a compile-time problem, but I don't see a way to do
this at compile-time except by using vendor-specific compiler
extensions. (ISTR VC having some macro that expands to different
integers for each usage.)
>I think this problem should be quite common, so I thought maybe
someone can suggest a better design than that which requires the
enum/defines list.

I think so, too.
What are you trying to do with your event/state couples?
I have a table which defines for each incoming event/state the handler
to call. So I need an index for each event subtype, and I need the
number of the the events to be known when I build the table in the
constructor of the objects which defines and use that table.

Thanks for your help, regards.
Sep 23 '08 #8
On 2008-09-22, Kai-Uwe Bux <jk********@gmx.netwrote:
puzzlecracker wrote:
[...]
>I think it's better to eliminate count function altogether and put the
count functionality into class/struct such as, in your case, reg_base.
struct counter{

static unsigned int count getId(return id++;)

private:
static unsigned int id;

};
unsigned int counter::id=0;
Or some cleaner variation of that. I don't like member-less function
in the code. At the very least, we ought to namespace it if we're to
have this function, given that it's short to use and easier to code
than an alternative I've just mentioned.

Yup. Also, get_id() wasn't const. Here is a cleaner version:

class reg_base {
protected:

static
unsigned int
count ( void ) {
static unsigned int c = 0;
return ( c++ );
}

public:

virtual
unsigned int get_id ( void ) const = 0;

virtual
~reg_base ( void ) {}

};

template < typename D >
class reg : public reg_base {

static unsigned int const the_id;

public:

unsigned int get_id ( void ) const {
return ( the_id );
}

static
unsigned int id ( void ) {
return ( the_id );
}

virtual
~reg ( void ) {}

};

template < typename D >
unsigned int const reg<D>::the_id = reg<D>::reg_base::count();
struct X : public reg<X{};
struct Y : public reg<Y{};

#include <iostream>

int main ( void ) {
X x;
Y y1;
Y y2;
reg_base * px = new X ();
reg_base * py = new Y ();

std::cout << "X " << x.get_id() << '\n';
std::cout << "Y " << y1.get_id() << '\n';
std::cout << "Y " << y2.get_id() << '\n';

std::cout << "X " << px->get_id() << '\n';
std::cout << "Y " << py->get_id() << '\n';

std::cout << "X " << X::id() << '\n';
std::cout << "Y " << Y::id() << '\n';

delete ( px );
delete ( py );
}
Yes, I tried it and it is indeed what I need. Only what I also need
would be a static method which returns the total number of objects
already registered.

But what I need most now is a crash course on templates ;-).

Thanks so much for all the help, you rock guys!!!
Sep 23 '08 #9
Stefano Sabatini wrote:
[snip]
Yes, I tried it and it is indeed what I need. Only what I also need
would be a static method which returns the total number of objects
already registered.
Objects or classes?

Assuming classes, this poses an interesting problem. Here are two attempts:

a)

class reg_base {
protected:

static
unsigned int &
the_count ( void ) {
static unsigned int c = 0;
return ( c );
}

static
unsigned int count ( void ) {
return ( the_count() ++ );
}

public:

static
unsigned int num_classes ( void ) {
return ( the_count() );
}

virtual
unsigned int get_id ( void ) const = 0;

virtual
~reg_base ( void ) {}

};

template < typename D >
class reg : public reg_base {

static unsigned int const the_id;

public:

unsigned int get_id ( void ) const {
return ( the_id );
}

static
unsigned int id ( void ) {
return ( the_id );
}

virtual
~reg ( void ) {}

};

template < typename D >
unsigned int const reg<D>::the_id = reg<D>::reg_base::count();
struct X : public reg<X{};
struct Y : public reg<Y{};
struct Z : public reg<Z{};

#include <iostream>

int main ( void ) {
std::cout << "Classes: " << reg_base::num_classes() << '\n';

X x;
Y y1;
Y y2;
reg_base * px = new X ();
reg_base * py = new Y ();

std::cout << "X " << x.get_id() << '\n';
std::cout << "Y " << y1.get_id() << '\n';
std::cout << "Y " << y2.get_id() << '\n';

std::cout << "X " << px->get_id() << '\n';
std::cout << "Y " << py->get_id() << '\n';

std::cout << "X " << X::id() << '\n';
std::cout << "Y " << Y::id() << '\n';

delete ( px );
delete ( py );
}
This one does not count the class Z. Honestly, I don't know the reason.
b)

class reg_base {
protected:

static
unsigned int &
the_count ( void ) {
static unsigned int c = 0;
return ( c );
}

static
unsigned int count ( void ) {
return ( the_count() ++ );
}

public:

static
unsigned int num_classes ( void ) {
return ( the_count() );
}

virtual
unsigned int get_id ( void ) const = 0;

virtual
~reg_base ( void ) {}

};

template < typename D >
class reg : public reg_base {

static
unsigned int & the_id ( void ) {
static unsigned int dummy = 0;
return ( dummy );
}

struct do_register {

do_register ( void ) {
the_id() = reg<D>::reg_base::count();
}

};

public:

reg ( void ) {
static do_register dummy;
}

unsigned int get_id ( void ) const {
return ( the_id() );
}

static
unsigned int id ( void ) {
return ( the_id() );
}

virtual
~reg ( void ) {}

};
struct X : public reg<X{};
struct Y : public reg<Y{};
struct Z : public reg<Z{};

#include <iostream>

int main ( void ) {
std::cout << "Classes: " << reg_base::num_classes() << '\n';
X x;
std::cout << "Classes: " << reg_base::num_classes() << '\n';
Y y1;
Y y2;
std::cout << "Classes: " << reg_base::num_classes() << '\n';
Z z;
std::cout << "Classes: " << reg_base::num_classes() << '\n';
reg_base * px = new X ();
reg_base * py = new Y ();

std::cout << "X " << x.get_id() << '\n';
std::cout << "Y " << y1.get_id() << '\n';
std::cout << "Y " << y2.get_id() << '\n';

std::cout << "X " << px->get_id() << '\n';
std::cout << "Y " << py->get_id() << '\n';

std::cout << "X " << X::id() << '\n';
std::cout << "Y " << Y::id() << '\n';

delete ( px );
delete ( py );
std::cout << "Classes: " << reg_base::num_classes() << '\n';
}

This one counts each class, once the first object of that class has been
constructed.

I don't know, which semantics you actually need.

Best

Kai-Uwe Bux
Sep 23 '08 #10
On 2008-09-23 16:51, Stefano Sabatini wrote:
On 2008-09-22, Erik Wikström <Er***********@telia.comwrote:
>On 2008-09-22 16:14, Stefano Sabatini wrote:
>>I think this problem should be quite common, so I thought maybe
someone can suggest a better design than that which requires the
enum/defines list.

It seems like you have a problem with your design. If you want to use
the number to distinguish the different events and based on that perform
different actions perhaps you should consider overloading some function
for the different event types instead.

Well in this case I need to redefine a different integer for every
object type, this because that index is used to access a table.
This table defines an handler to be called for each state/event
couple, that is for each event arrived I want to perform a different
action based on the state of the object.
I seems I was not clear enough about what I meant, so perhaps an example
will do instead:

#include <iostream>

// Classes that represents the different events
struct Event { };
struct FooEvent : public Event { };
struct BarEvent : public Event { };
// Functions to handle events in state A
void stateA(const Event& e)
{
std::cout << "Generic event handler when in state A\n";
}

void stateA(const FooEvent& e)
{
std::cout << "Handler for Foo events when in state A\n";
}
int main()
{
FooEvent foo;
BarEvent bar;

stateA(foo);
stateA(bar);

return 0;
}

Using this scheme it is easy to add new events and you only have to
update the code for those states which can handle the events (by
overloading the event-handler for the new event).

--
Erik Wikström
Sep 23 '08 #11
On 2008-09-23 19:40, Erik Wikström wrote:
On 2008-09-23 16:51, Stefano Sabatini wrote:
>On 2008-09-22, Erik Wikström <Er***********@telia.comwrote:
>>On 2008-09-22 16:14, Stefano Sabatini wrote:
>>>I think this problem should be quite common, so I thought maybe
someone can suggest a better design than that which requires the
enum/defines list.

It seems like you have a problem with your design. If you want to use
the number to distinguish the different events and based on that perform
different actions perhaps you should consider overloading some function
for the different event types instead.

Well in this case I need to redefine a different integer for every
object type, this because that index is used to access a table.
This table defines an handler to be called for each state/event
couple, that is for each event arrived I want to perform a different
action based on the state of the object.

I seems I was not clear enough about what I meant, so perhaps an example
will do instead:

#include <iostream>

// Classes that represents the different events
struct Event { };
struct FooEvent : public Event { };
struct BarEvent : public Event { };
// Functions to handle events in state A
void stateA(const Event& e)
{
std::cout << "Generic event handler when in state A\n";
}

void stateA(const FooEvent& e)
{
std::cout << "Handler for Foo events when in state A\n";
}
int main()
{
FooEvent foo;
BarEvent bar;

stateA(foo);
stateA(bar);

return 0;
}

Using this scheme it is easy to add new events and you only have to
update the code for those states which can handle the events (by
overloading the event-handler for the new event).
I realised that you might want to be able to somehow store the state,
and I can see two ways of doing that. Either you can use create objects
for the states and overload the event handler function for both state
and event:

struct Event {};
struct FooEvent : public Event {};

struct State {};
struct BarState : public State {};
void eventHandler(const BarState& s, const Event& e)
{
// General event handler for state Bar
}

void eventHandler(const BarState& s, const FooEvent& e)
{
// Foo event handler for state Bar
}

The second alternative (which I think might be a bit more elegant) is to
make the event handlers member-functions of state-objects:
struct Event {};
struct FooEvent : public Event {};

struct State {};

struct BarState : public State
{
void handleEvent(const FooEvent& e)
{
// Handle Foo events
}

void handleEvent(const Event& e)
{
// General event handler
}
};

--
Erik Wikström
Sep 23 '08 #12
On 2008-09-23 20:32, Erik Wikström wrote:
The second alternative (which I think might be a bit more elegant) is to
make the event handlers member-functions of state-objects:
struct Event {};
struct FooEvent : public Event {};

struct State {};

struct BarState : public State
{
void handleEvent(const FooEvent& e)
{
// Handle Foo events
}

void handleEvent(const Event& e)
{
// General event handler
}
};

Actually, that won't work (remind me not to write code when I'm tired),
you would need something like double dispatch to get it to work.

--
Erik Wikström
Sep 23 '08 #13
Kai-Uwe Bux wrote:
Stefano Sabatini wrote:
[snip]
>Yes, I tried it and it is indeed what I need. Only what I also need
would be a static method which returns the total number of objects
already registered.

Objects or classes?

Assuming classes, this poses an interesting problem. Here are two attempts:

a)

class reg_base {
protected:

static
unsigned int &
the_count ( void ) {
static unsigned int c = 0;
return ( c );
}

static
unsigned int count ( void ) {
return ( the_count() ++ );
}

public:

static
unsigned int num_classes ( void ) {
return ( the_count() );
}

virtual
unsigned int get_id ( void ) const = 0;

virtual
~reg_base ( void ) {}

};

template < typename D >
class reg : public reg_base {

static unsigned int const the_id;

public:

unsigned int get_id ( void ) const {
return ( the_id );
}

static
unsigned int id ( void ) {
return ( the_id );
}

virtual
~reg ( void ) {}

};

template < typename D >
unsigned int const reg<D>::the_id = reg<D>::reg_base::count();
struct X : public reg<X{};
struct Y : public reg<Y{};
struct Z : public reg<Z{};

#include <iostream>

int main ( void ) {
std::cout << "Classes: " << reg_base::num_classes() << '\n';

X x;
Y y1;
Y y2;
reg_base * px = new X ();
reg_base * py = new Y ();

std::cout << "X " << x.get_id() << '\n';
std::cout << "Y " << y1.get_id() << '\n';
std::cout << "Y " << y2.get_id() << '\n';

std::cout << "X " << px->get_id() << '\n';
std::cout << "Y " << py->get_id() << '\n';

std::cout << "X " << X::id() << '\n';
std::cout << "Y " << Y::id() << '\n';

delete ( px );
delete ( py );
}
This one does not count the class Z. Honestly, I don't know the reason.
Most likely, the optimizer throws Z away (and the instantiation of the
base class as well), since it isn't used anywhere in the program. Built
without optimization with VC++ 2008 (the "Debug" configuration), the
program reports 3 classes, built optimized it reports only 2.
[..]
Best

Kai-Uwe Bux
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 23 '08 #14
Victor Bazarov wrote:
Kai-Uwe Bux wrote:
[snip]
>class reg_base {
protected:

static
unsigned int &
the_count ( void ) {
static unsigned int c = 0;
return ( c );
}

static
unsigned int count ( void ) {
return ( the_count() ++ );
}

public:

static
unsigned int num_classes ( void ) {
return ( the_count() );
}

virtual
unsigned int get_id ( void ) const = 0;

virtual
~reg_base ( void ) {}

};

template < typename D >
class reg : public reg_base {

static unsigned int const the_id;

public:

unsigned int get_id ( void ) const {
return ( the_id );
}

static
unsigned int id ( void ) {
return ( the_id );
}

virtual
~reg ( void ) {}

};

template < typename D >
unsigned int const reg<D>::the_id = reg<D>::reg_base::count();
struct X : public reg<X{};
struct Y : public reg<Y{};
struct Z : public reg<Z{};

#include <iostream>

int main ( void ) {
std::cout << "Classes: " << reg_base::num_classes() << '\n';

X x;
Y y1;
Y y2;
reg_base * px = new X ();
reg_base * py = new Y ();

std::cout << "X " << x.get_id() << '\n';
std::cout << "Y " << y1.get_id() << '\n';
std::cout << "Y " << y2.get_id() << '\n';

std::cout << "X " << px->get_id() << '\n';
std::cout << "Y " << py->get_id() << '\n';

std::cout << "X " << X::id() << '\n';
std::cout << "Y " << Y::id() << '\n';

delete ( px );
delete ( py );
}
This one does not count the class Z. Honestly, I don't know the reason.

Most likely, the optimizer throws Z away (and the instantiation of the
base class as well), since it isn't used anywhere in the program. Built
without optimization with VC++ 2008 (the "Debug" configuration), the
program reports 3 classes, built optimized it reports only 2.
[snip]

Hm, interesting.

That indicates, that the output is either undefined or implementation
defined. That in turn poses the question, where in the program I invoke
undefined or implementation defined behavior. Got to take a closer look; as
of now, I am quite puzzled.
Best

Kai-Uwe Bux
Sep 24 '08 #15
On 23 Sep, 19:26, Kai-Uwe Bux <jkherci...@gmx.netwrote:
Stefano Sabatini wrote:

[snip]
Yes, I tried it and it is indeed what I need. Only what I also need
would be a static method which returns the total number of objects
already registered.

Objects or classes?

Assuming classes, this poses an interesting problem. Here are two attempts:

a)

class reg_base {
protected:

* static
* unsigned int &
* the_count ( void ) {
* * static unsigned int c = 0;
* * return ( c );
* }

* static
* unsigned int count ( void ) {
* * return ( the_count() ++ );
* }

public:

* static
* unsigned int num_classes ( void ) {
* * return ( the_count() );
* }

* virtual
* unsigned int get_id ( void ) const = 0;

* virtual
* ~reg_base ( void ) {}

};

template < typename D >
class reg : public reg_base {

* static unsigned int const the_id;

public:

* unsigned int get_id ( void ) const {
* * return ( the_id );
* }

* static
* unsigned int id ( void ) {
* * return ( the_id );
* }

* virtual
* ~reg ( void ) {}

};

template < typename D >
unsigned int const reg<D>::the_id = reg<D>::reg_base::count();

struct X : public reg<X{};
struct Y : public reg<Y{};
struct Z : public reg<Z{};

#include <iostream>

int main ( void ) {
* std::cout << "Classes: " << reg_base::num_classes() << '\n';

* X x;
* Y y1;
* Y y2;
* reg_base * px = new X ();
* reg_base * py = new Y ();

* std::cout << "X " << x.get_id() << '\n';
* std::cout << "Y " << y1.get_id() << '\n';
* std::cout << "Y " << y2.get_id() << '\n';

* std::cout << "X " << px->get_id() << '\n';
* std::cout << "Y " << py->get_id() << '\n';

* std::cout << "X " << X::id() << '\n';
* std::cout << "Y " << Y::id() << '\n';

* delete ( px );
* delete ( py );

}

This one does not count the class Z. Honestly, I don't know the reason.
I think the reason is that even if reg<Zis implicitly instantiated
by the declaration of
struct Z : public reg<Z>, this does not cause the members of reg<Zto
be instantiated.

Consider the following, from [temp.inst]/1: (annotations in brackets)

(...)in particular, the initialization (and any associated side-
effects) [in this case, increasing the counter] of a static data
member [of a class template] does not occur unless the static data
member is itself used in a way that requires the definition of the
static data member to exist. [never happens, since Z::the_id is never
referenced]

DP
Sep 24 '08 #16
Stefano Sabatini wrote:
On 2008-09-22, Hendrik Schober <sp******@gmx.dewrote:
>Stefano Sabatini wrote:
>>Hi all,

I'm facing this design problem.

I have a table which defines the behaviour of an Object in a given
state according to the type of event it is receiving.

So for each couple event,state I want I set in the table a different
handler.

My trivial implementation make use of defines (but I could have used
an enum as well).

So I have:
#define EVT_FOO 0
#define EVT_BAR 1
....
#define EVT_FOOBAR N

Then I define for each event a virtual GetType() which returns the
event type.
What are you doing with these event/state couples?
Could it be that what you need is multi-methods?
Have you looked into patterns? I suspect that there are much
better ways to achieve whatever you're trying to do.

Mmmh... do you mean something like this:
http://www.codeproject.com/KB/recipes/mmcppfcs.aspx
?
Maybe. I haven't looked at this specific implementation. What
I meant was the general problem domain know as multi-methods.
If you need to call a function depending on one object's type,
in C++ you use virtual functions. If you need to pick a function
depending on the types of more than one object, then you need
multi-methods and that means in C++ you're on your own.

There are quiet a few implementations of them floating around.
IIRC, Bjarne Stroustrup's "Desgin & Evolution of C++" had a few
pages dedicated to the problem and I think one of Scott Meyer's
"(More) Effective C++" discussed it, too. (I have neither one
around here, so I can't check, but I could do so later if you
cannot find out about them otherwise.)
I suggest you read those and/or a few other discussions of the
problem to find out if that's what you need.

From what I heard about your problem so far, with just the two
objects you have, the double-dispatch idiom that Erik mentioned
might be the best solution.
Yes I should know better patterns...
Read the GoF book. It's worth the while.
>>This is ugly and awkward, since everytime I add an event I have to
update the enum/list of defines, while I would like to be able to
automatically get a different integer for every derived class of
Event.

Mayeb I could get this result with some kind of run-time registration
mechanism.
It seems a compile-time problem, but I don't see a way to do
this at compile-time except by using vendor-specific compiler
extensions. (ISTR VC having some macro that expands to different
integers for each usage.)
>>I think this problem should be quite common, so I thought maybe
someone can suggest a better design than that which requires the
enum/defines list.
I think so, too.
What are you trying to do with your event/state couples?

I have a table which defines for each incoming event/state the handler
to call. So I need an index for each event subtype, and I need the
number of the the events to be known when I build the table in the
constructor of the objects which defines and use that table.
You do not necessarily need an integer-indexed table. If you
use multi-indexed maps, you can use whatever you want (well,
provided it can be ordered) to find the right method (with
'std::type_info' IMHO being a rather obvious first candidate
to look at).
Thanks for your help, regards.
Schobi
Sep 24 '08 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Anand | last post by:
class base: def __setattr__(self,attr,key,*unexpected): print "Base Class :",attr,key,unexpected,self.__dict__ self.__dict__ = key def __getattr__(self,attr,*unexpected): print "Base Class...
14
by: Sridhar R | last post by:
Consider the code below, class Base(object): pass class Derived(object): def __new__(cls, *args, **kwds): # some_factory returns an instance of Base # and I have to derive from this...
1
by: Art | last post by:
This is partially an academic question, but I'm trying to understand templates better. I have a base class that uses template parameters to define the behavior of its class. I want to subclass this...
1
by: Bren | last post by:
I'm hoping somebody can help me with the following problem. I'm hoping it's not insurmountable. Here's a basic structure: class EventTarget { public: EventTarget(); virtual ~EventTarget();
7
by: Baski | last post by:
Base class: class AssetBase { string _clli; public string CLLI { get
6
by: John Glover | last post by:
I'm having a very strange problem with XML serialization. I'm writing web services which pass instances of various classes back and forth as parameters and return values of web methods. The...
3
by: craig | last post by:
Given two existing but different classes OldA and OldB (that can not be made to derive from any new base class); is there a way to make them both "observer" objects so that they can be put in one...
7
by: Steven Bethard | last post by:
I've updated PEP 359 with a bunch of the recent suggestions. The patch is available at: http://bugs.python.org/1472459 and I've pasted the full text below. I've tried to be more explicit about...
1
by: PengYu.UT | last post by:
Hi, Are there any walkaround to enable functions in the derived class with the same function name but different return type? In the following example, D1 and D2 are B's derived class. I want...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.