473,402 Members | 2,053 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,402 software developers and data experts.

Finding a max for an enum - a template problem

I'm creating a template to support state machines. In doing so, I
need to pass an enumeration for the number of transitions and a non
type parameter for the range of the enum (to allow me to allocate an
array of pointers big enough to hold one entry for each transition).
My template declaration looks roughly like this:

template <class TRANSITION, int NUMTRANSITIONS>
class StateMachine {
***SNIP***
void RegisterTransition(TRANSITION t, StateMachine *pState);
StateMachine *nextState[NUMTRANSITIONS];
***SNIP***
};
I invoke the template like so:

// Define an enumerated type for transitions
enum ToggleSwitch_t { ON, OFF, TOGGLE };
#define MAX_TRANSITION 3

// Set up a pointer to current state
StateMachine<ToggleSwitch_t, MAX_TRANSITION*pCurrState;

// Create states
StateMachine<ToggleSwitch_t, MAX_TRANSITION>LightOn("LIGHT ON");
StateMachine<ToggleSwitch_t, MAX_TRANSITIONLightOff("LIGHT OFF");

// Set up transitions
LightOn.RegisterTransition(ON, &LightOn);
LightOn.RegisterTransition(OFF, &LightOff);
LightOn.RegisterTransition(TOGGLE, &LightOff);

LightOff.RegisterTransition(ON, &LightOn);
LightOff.RegisterTransition(OFF, &LightOff);
LightOff.RegisterTransition(TOGGLE, &LightOn);

It works fine as is, but I want to add a static array that will allow
me to index into states as an enum type. I could set up something
like

template <class TRANSITION, int NUMTRANSITIONS, class STATE, int
NUMSTATES>

but this is going to get very hairy very quickly. I would prefer if I
could somehow take the enum that's passed in and simply derive its
maximum from inside the template itself. That would give me something
easier to read like

template <class TRANSITION, class STATE>

I can't find any way to determine the max value of an enum. Most
previous posts are of the form "You can't do that - please try
workaround XYZ..." If I must, I could try using #define macros, but
that just seems to hide the mechanics rather than simplifying them,
which is a sure recipe for confusion for maintenance programming.

Does anyone have any suggestions?

Thanks,

Kevin

Jun 21 '07 #1
7 7875
Kevin wrote:
[..] I would prefer if I
could somehow take the enum that's passed in and simply derive its
maximum from inside the template itself.
There is no way.
[..]
I can't find any way to determine the max value of an enum.
Because there is none.
Most
previous posts are of the form "You can't do that - please try
workaround XYZ..." If I must, I could try using #define macros, but
that just seems to hide the mechanics rather than simplifying them,
which is a sure recipe for confusion for maintenance programming.

Does anyone have any suggestions?
You can't do that - please try workaround: each "enum" should not
really be an enum, but an array of, say, unsigned, wrapped in a class
or a struct (to make it a different type). The array of values will
have its size, from which you can determine when you hit the end of
the array, thus going through all values.

Enums are ancient and not very suitable for state machine modelling.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 21 '07 #2
You can do something like

enum ToggleSwitch_t { ON, OFF, TOGGLE, LAST };

and then take the value of LAST. You would need LAST to be the last
element in every enum you want to use.
On Jun 21, 12:57 pm, Kevin <k...@collins.rockwell.comwrote:
I'm creating a template to support state machines. In doing so, I
need to pass an enumeration for the number of transitions and a non
type parameter for the range of the enum (to allow me to allocate an
array of pointers big enough to hold one entry for each transition).
My template declaration looks roughly like this:

template <class TRANSITION, int NUMTRANSITIONS>
class StateMachine {
***SNIP***
void RegisterTransition(TRANSITION t, StateMachine *pState);
StateMachine *nextState[NUMTRANSITIONS];
***SNIP***
};

I invoke the template like so:

// Define an enumerated type for transitions
enum ToggleSwitch_t { ON, OFF, TOGGLE };
#define MAX_TRANSITION 3

// Set up a pointer to current state
StateMachine<ToggleSwitch_t, MAX_TRANSITION*pCurrState;

// Create states
StateMachine<ToggleSwitch_t, MAX_TRANSITION>LightOn("LIGHT ON");
StateMachine<ToggleSwitch_t, MAX_TRANSITIONLightOff("LIGHT OFF");

// Set up transitions
LightOn.RegisterTransition(ON, &LightOn);
LightOn.RegisterTransition(OFF, &LightOff);
LightOn.RegisterTransition(TOGGLE, &LightOff);

LightOff.RegisterTransition(ON, &LightOn);
LightOff.RegisterTransition(OFF, &LightOff);
LightOff.RegisterTransition(TOGGLE, &LightOn);

It works fine as is, but I want to add a static array that will allow
me to index into states as an enum type. I could set up something
like

template <class TRANSITION, int NUMTRANSITIONS, class STATE, int
NUMSTATES>

but this is going to get very hairy very quickly. I would prefer if I
could somehow take the enum that's passed in and simply derive its
maximum from inside the template itself. That would give me something
easier to read like

template <class TRANSITION, class STATE>

I can't find any way to determine the max value of an enum. Most
previous posts are of the form "You can't do that - please try
workaround XYZ..." If I must, I could try using #define macros, but
that just seems to hide the mechanics rather than simplifying them,
which is a sure recipe for confusion for maintenance programming.

Does anyone have any suggestions?

Thanks,

Kevin

Jun 21 '07 #3
On Jun 21, 10:06 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:

You can't do that - please try workaround: each "enum" should not
really be an enum, but an array of, say, unsigned, wrapped in a class
or a struct (to make it a different type). The array of values will
have its size, from which you can determine when you hit the end of
the array, thus going through all values.

So, something like:
template <int TRANSITIONS[], int STATES[]>
class StateMachine {
***SNIP***
StateMachine *nextState[sizeof(TRANSITIONS)];
***SNIP***
};

And

#define ON 1
#define OFF 2
#define TOGGLE 3
int MyTrans[] = {ON, OFF, TOGGLE};

#define LIGHT_ON 1
#define LIGHT_OFF 2
int MyStates[] = {LIGHT_ON, LIGHT_OFF, TOGGLE};

StateMachine<MyTrans, MyStates>LightOn("LIGHT IS ON");
StateMachine<MyTrans, MyStatesLightOff("LIGHT IS OFF");

Does that seem right?

- Kevin

Jun 21 '07 #4
Kevin wrote:
On Jun 21, 10:06 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:

>You can't do that - please try workaround: each "enum" should not
really be an enum, but an array of, say, unsigned, wrapped in a class
or a struct (to make it a different type). The array of values will
have its size, from which you can determine when you hit the end of
the array, thus going through all values.


So, something like:
template <int TRANSITIONS[], int STATES[]>
class StateMachine {
***SNIP***
StateMachine *nextState[sizeof(TRANSITIONS)];
Probably

StateMachine *nextState[sizeof(TRANSITIONS) / sizeof(int)];

(sizeof does not report the *number* of elements, but their combined
size in bytes).
***SNIP***
};

And

#define ON 1
#define OFF 2
#define TOGGLE 3
int MyTrans[] = {ON, OFF, TOGGLE};

#define LIGHT_ON 1
#define LIGHT_OFF 2
int MyStates[] = {LIGHT_ON, LIGHT_OFF, TOGGLE};

StateMachine<MyTrans, MyStates>LightOn("LIGHT IS ON");
StateMachine<MyTrans, MyStatesLightOff("LIGHT IS OFF");

Does that seem right?
Since you're asking in response to my reply, I feel I need to give you
an answer, but you're not going to like it, I'm afraid... Here it is:
I have no idea. If it solves the problem you had, then use it. If it
does not, let's talk more, perhaps you'll get me to understand what it
is you hope to accomplish.

I know that enums are not well suited for your task, they are very low
level and very limited functionality types. That's why I suggested
dumping them altogether. You are better off creating a separate type
for every state set/sequence you need to identify. Each state then
could be expressed/encoded by a value.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jun 21 '07 #5
On Jun 21, 8:54 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
Kevin wrote:
On Jun 21, 10:06 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
[...]
Since you're asking in response to my reply, I feel I need to give you
an answer, but you're not going to like it, I'm afraid... Here it is:
I have no idea.
It's interesting to note that most of the experts, when
designing state machines for C++, have written code generators
to do it. Of course, most of this goes back to before the days
of template meta-programming, but as far as I know, no one has
come up with a better solution. You define a higher level
language in which you define the transitions, and a "compiler"
for that language which generates the C++.

In general, I'd say that this is to be prefered over template
meta-programming any time the "program" itself didn't need to
exploit information internal to C++ (like types, etc.). The
results are almost always more readable.
If it solves the problem you had, then use it. If it
does not, let's talk more, perhaps you'll get me to understand what it
is you hope to accomplish.
I know that enums are not well suited for your task, they are very low
level and very limited functionality types. That's why I suggested
dumping them altogether. You are better off creating a separate type
for every state set/sequence you need to identify. Each state then
could be expressed/encoded by a value.
Enums can have a role to play in a state machine, but they
certainly aren't a state machine. The "classical" solution, I
think, is along the lines you suggest: a base class State, and
each individual state a distinct class deriving from this base,
with transitions, actions, etc. being handled by virtual
functions in State.

You might want to check out http://smc.sourceforge.net/. This
seems to be derived from Robert Martin's work in the 1990's,
which is, as far as I know, still the reference. (Note: I've
not used this tool, and only stumbled upon it looking for
information about Robert Martin's state machine compiler.)

--
James Kanze (GABI Software, from CAI) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 22 '07 #6
Kevin a écrit :
I'm creating a template to support state machines. In doing so, I
need to pass an enumeration for the number of transitions and a non
type parameter for the range of the enum (to allow me to allocate an
array of pointers big enough to hold one entry for each transition).
[snip]

I can't find any way to determine the max value of an enum. Most
previous posts are of the form "You can't do that - please try
workaround XYZ..." If I must, I could try using #define macros, but
that just seems to hide the mechanics rather than simplifying them,
which is a sure recipe for confusion for maintenance programming.
Did you have a look at the "Variadic Integral Constant" MPL concept in
boost:
http://www.boost.org/libs/mpl/doc/re...e-wrapper.html

Instead of passing all enum, it could make sense to allow the
specification of the enums to use for the states.

typedef vector_c<states,ON,OFF,FAIL> base_protocol;
typedef typedef push_back<base_protocol,
integral_c<states,TRANSMIT::type
halfduplex_transmit;
typedef typedef push_back<base_protocol,
integral_c<states,RECEIVE::type halfduplex_receive;
typedef vector_c<states,ON,OFF,FAIL,
RECEIVE,TRANSMIT,COLLISION> full_duplex;
//...

Michael
Jun 22 '07 #7
James Kanze wrote:
It's interesting to note that most of the experts, when
designing state machines for C++, have written code generators
to do it. Of course, most of this goes back to before the days
of template meta-programming, but as far as I know, no one has
come up with a better solution.
I guess it depends on what you mean with "better" here. There are TMP
FSM solutions:
- Aleksey Gurtovoy's MPL example
http://www.mywikinet.com/mpl/fsm_example_25_jul_02.zip shows how a
simple but fast STT-based FSM can be implemented
- Boost.Statechart <http://www.boost.org/libs/statechartprovides much
of the UML functionality, including substates and concurrent states
You define a higher level
language in which you define the transitions, and a "compiler"
for that language which generates the C++.
I believe for quite a few problems there's no longer any need for such
external (front-end) compilers. C++ itself offers all the necessary
machinery to do the generation in the language itself, as libraries like
Boost.Spirit very nicely demostrate.
In general, I'd say that this is to be prefered over template
meta-programming any time the "program" itself didn't need to
exploit information internal to C++ (like types, etc.)
Which is the case for state machines, isn't it? You usually want to
write entry-, exit- and transition-actions in C++.

Regards,

--
Andreas Huber

When replying by private email, please remove the words spam and trap
from the address shown in the header.

Jun 23 '07 #8

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

Similar topics

1
by: Alexander Stippler | last post by:
Hello, some time ago I learnt much about restricting template parameters by checking some properties upon these and exploiting SFINAE. But the existence of unnamed enum types makes me doubt if...
7
by: wogston | last post by:
A) template <typename scalar, int size> struct basevector { enum { size = size }; scalar v; }; B)
8
by: Imran | last post by:
Hello All I have a enum decla like this enum Days // Declare enum type Days { saturday, // saturday = 0 by default sunday = 0, // sunday = 0 as well monday, ...
0
by: Vaclav Haisman | last post by:
Motivation: I have been working on some project recently that uses lots of enums with disjunctive intervals of values because it is rather convenient way to define series of constants with...
8
by: Klaus Schneider | last post by:
Hi all! I'm having trouble with a template function with variable arguments when I parse an enum type as variable argument. Example: template <class T> bool test(int num, ...) { va_list ap;...
1
by: Karine Pinault | last post by:
I am having trouble trying to compile existing code with the /clr flag. The following error occurs and I can't figure it out how to fix this problem. I have the following declaration:...
10
by: Randy | last post by:
Hi, Can anyone point me to a complete, compilable example of Besser's ENUM++ mechanism? I downloaded it from CUJ and gave it a try but got errors just trying to compile the header enum.h. ...
19
by: Rahul | last post by:
Hi, Is there a way to find the offset of a class member at compile time. e.g. class A{ int i; int j; char c; }; Here the offset of c = 8 bytes from the start of an object of A (assuming 4...
16
by: Hendrik Schober | last post by:
Hi, suppose we have template< typename T > struct X; and some specializations: template<>
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
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...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.