|
Boost Users : |
From: Rush Manbert (rush_at_[hidden])
Date: 2005-10-10 13:08:40
Hi all,
I posted this question to comp.lang.c++.moderated and got a single
reply that basically said "it looks like you need to use macros",
but I thought I would ask the same question here, just in case you
MPL folks have some tricks up your boost library sleeves. Basically,
I need to make an enum and a static array of structures from one
data set and I only know one way to do it, and it involves an amount
of "trickiness" that some find disturbing.
The original post:
In the code shown below, the CODE_TABLE macro is used to insert a
sequence of CODE(codeValue) macros. By changing the definition of
CODE(codeValue) right before each usage of CODE_TABLE, I can create
an enumeration of codeValues, then use the same CODE_TABLE definition
to create a static lookup table that can be used to find information
about a codeValue, given its numeric value. In this case, I am finding
the name of the enumerated value. In the real application, there
are a number of other fields available. (As you can probably tell, I
have written a lot of C code in my time.)
IMHO, the benefit of this technique is that you only maintain
CODE_TABLE. All of the required code bits are generated from it. The
downside is that Macros are Evil, the macro-that-is-a-list-of-macros
is confusing, and you need to carefully redefine CODE(codeValue) in
the proper locations. Additionally, the real application will have
multiple classes that each define their own CODE_TABLE contents, so
making it all work correctly is a little tricky.
My question is this: Is there any method available in C++ that can let
me do away with the macros while preserving the nice quality that only
one data structure needs to be maintained? Something sophisticated and
tricky with templates perhaps? I expect that the fact that I stringize
the enum name when creating the lookup table makes a macro the only
choice. But, since that is only one component in each lookup table
entry in the real code, I might be willing to give it up in order to
lose the macros.
Here is the code example.
Contents of foo.h:
-----------------
#define CODE_TABLE \
CODE(FooCodeA) \
CODE(FooCodeB)
#define CODE(codeValue) codeValue,
class foo
{
public:
typedef enum
{ // Here comes the first use of CODE_TABLE
CODE_TABLE
} CodesT;
foo (CodesT theCode) : m_code (theCode) {}
const char *lookup (void) const;
const int getCode (void) const {return m_code;}
private:
CodesT m_code;
typedef struct
{
CodesT theCode;
const char *pTheCodeAsString;
} CodeLookupTableT;
static CodeLookupTableT m_lookupTable[];
};
Contents of foo.cpp:
-------------------
#include "foo.h"
// Now we redefine CODE so that we can initialize the
// static lookup table
#undef CODE
#define CODE(codeValue) {codeValue, #codeValue},
foo::CodeTableLookupT foo::m_lookupTable[] = { CODE_TABLE };
// The lookup method that finds the string description
// from the numeric code
const char *foo::lookup (void) const {
for (int i = 0;
i < (sizeof m_lookupTable)/(sizeof m_lookupTable[0]);
++i) {
if (m_lookupTable[i].theCode == m_code)
return m_lookupTable[i].pTheCodeAsString;
}
return "Unknown code value";
}
contents of main.cpp:
-------------------
#include <iostream>
#include "foo.h"
using namespace std;
int main (int argc, char * const argv[])
{
foo myFoo (foo::FooCodeB);
cout << "myFoo with code number....: " << myFoo.getCode() << endl
<< " looks up the code name as: " << myFoo.lookup() << endl;
return 0;
}
Output from running the program:
-------------------------------
myFoo with code number....: 1
looks up the code name as: FooCodeB
Thanks,
Rush
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net