Setting enumerated values based on string representions - c++

I have a config file containing string representations of an enum. There are a lot of different enum values. After loading the config, I need to work out enum values from it string representations. Ignoring macros, the only way I can think of doing this would be to create a hideous lookup function doing a string comparison against every possible value. Something like:
typedef enum Fields
{
FieldFlagNone,
FieldFlagOperation,
FieldFlagFormat,
...
}
Fields getFieldEnum(string fieldName){
if( fieldName.compare("FieldFlagNone") == 0 ){
return FieldFlagNone;
}else if( fieldName.compare("FieldFlagOperation") == 0 ){
return FieldFlagOperation;
}else if( fieldName.compare("FieldFlagFormat") == 0 ){
return FieldFlagFormat;
...
}
Is there a faster or more concise way of achieving the desired result?

You can use std::unordered_map<std::string, Fields>, that will speed up the conversion from linear time to constant time:
std::unordered_map<std::string, Fields> fieldsLookupTable {
{ "FieldFlagNone", FieldFlagNone },
...
};
To make it more concise you can use some macros:
#define LOOKUP_TABLE_ENTRY(x) { #x, x }
And then:
std::unordered_map<std::string, Fields> fieldsLookupTable {
LOOKUP_TABLE_ENTRY(FieldFlagNone),
LOOKUP_TABLE_ENTRY(FieldFlagOperation),
...
};
If you want to go really hardcore on eliminating duplication, you can do something like this:
#define ENUM_MODE_DEFINE 0
#define ENUM_MODE_LOOKUP 1
#define ENUM_BEGIN(x) \
#if ENUM_MODE == ENUM_MODE_DEFINE \
typedef enum x { \
#else \
#define LOOKUP_TABLE_NAME x ## LookupTable \
std::unordered_map<std::string, x> LOOKUP_TABLE_NAME; \
#endif
#define ENUM_ENTRY(x) \
#if ENUM_MODE == ENUM_MODE_DEFINE \
x, \
#else \
LOOKUP_TABLE_NAME[#x] = x; \
#endif
#define ENUM_END \
#if ENUM_MODE == ENUM_MODE_DEFINE \
} \
#else \
#undef LOOKUP_TABLE_NAME \
#endif
And then define your enum like this:
#define FIELDS \
ENUM_BEGIN(Fields) \
ENUM_ENTRY(FieldFlagNone) \
ENUM_ENTRY(FieldFlagOperation) \
...
ENUM_END
And where previously there was the enum definition, now there will be this:
#define ENUM_MODE ENUM_MODE_DEFINE
FIELDS
And somewhere else where you had the lookup table, you say this:
#define ENUM_MODE ENUM_MODE_LOOKUP
FIELDS
Basically the FIELDS macro uses the ENUM_BEGIN, ENUM_ENTRY and ENUM_END macros, which generate different code based on the value of ENUM_MODE. If you define it to be ENUM_MODE_DEFINE, then FIELDS will generate the enum definition. If you set it to ENUM_MODE_LOOKUP, it'll generate fieldsLookupTable.
This way we only used the enum entry names in FIELDS, so if you change something there, the lookup table and the enum definition will change automatically and won't go out of sync.

Related

#defined enum on Doxygen

So I have a #define that creates a "MY_ENUM" (minimal version)
#define MY_ENUM(ename, ...) \
namespace ename { \
enum ename { __VA_ARGS__, COUNT }; \
static std::string _Strings[COUNT]; \
static inline size_t size() {return COUNT;} \
}
This generates useful enums that can be created as:
/**
* #brief List of elements
*/
MY_ENUM(enuElements, Element1, Element2, Element3, Element4, Element5, Element6)
But generating the doc with doxygen doesn't seem to work => it mixes one enum with the following and some don't even appear.
I set:
MACRO_EXPANSION = YES
SKIP_FUNCTION_MACROS = NO
PREDEFINED = MY_ENUM(x) =
For what I have read, the answer is a proper setting of PREDEFINED but I haven't achieved, does anyone know how to create a document with this kind of defines?
Edit
Doxygen Version : 1.8.0
About why I think the clue is in PREDEFINED (but I might as well be wrong):
The site of Doxygen when talking about macros
This and this questions on SO
With the following code:
/// \file
#define MY_ENUM(ename, ...) \
namespace ename { \
enum ename { __VA_ARGS__, COUNT }; \
static std::string _Strings[COUNT]; \
static inline size_t size() {return COUNT;} \
}
/**
* #brief List of elements
*/
MY_ENUM(enuElements, Element1, Element2, Element3, Element4, Element5, Element6)
The setting (besides the default settings):
MACRO_EXPANSION = YES
and doxygen 1.9.1 I got:

Token detection within a C preprocessor macro argument

In order to nicely fix https://github.com/ned14/outcome/issues/244#issuecomment-774181015, I want to know if it is possible to detect whether a token sequence is present within a C preprocessor macro argument?
#define OUTCOME_TRY_GLUE2(x, y) x##y
#define OUTCOME_TRY_GLUE(x, y) OUTCOME_TRY_GLUE2(x, y)
#define OUTCOME_TRY_UNIQUE_NAME OUTCOME_TRY_GLUE(unique, __COUNTER__)
#define OUTCOME_TRYV2_SUCCESS_LIKELY(unique, ...) \
auto &&unique = (__VA_ARGS__)
#define OUTCOME_TRY2_SUCCESS_LIKELY(unique, v, ...) \
OUTCOME_TRYV2_SUCCESS_LIKELY(unique, __VA_ARGS__); \
v = std::move(unique).value()
#define OUTCOME_TRYA(v, ...) OUTCOME_TRY2_SUCCESS_LIKELY(OUTCOME_TRY_UNIQUE_NAME, v, __VA_ARGS__)
/* I'd like this to generate:
auto unique0 = (expr); auto x = std::move(unique0).value();
*/
OUTCOME_TRYA(auto x, expr);
/* I'd like this to generate:
auto &&unique1 = (expr); auto &&x = std::move(unique1).value();
*/
OUTCOME_TRYA(auto &&x, expr);
(https://godbolt.org/z/MW74cG may be more useful)
What one needs to achieve here is detection of && within the expansion of the v macro argument, but not if it is nested within ()<>".
Other answers on Stackoverflow can find a string within a C preprocessor macro argument, however those techniques can't work here because macro token paste of STRING_ ## && isn't legal. This level of C preprocessor hackery is beyond my capabilities, so I ask Stackoverflow. Thanks in advance for any help.
What one needs to achieve here is detection of && within the expansion of the v macro argument, but not if it is nested within ()<>".
No, it is not possible. I suggest separating the type from the name in a separate argument.
OUTCOME_TRYA_NEW(auto, x, expr);
OUTCOME_TRYA_NEW(auto &&, x, expr);
You could move the detection to runtime with stringify, like:
#define OUTCOME_TRYA(v, ...) \
if constexpr (your_constexpr_strstr(#v, "&&")) { \
/* do stuff with `auto &&` here */ \
} else { \
/* do stuff with `auto` here */ \
}
(or I think also with some std::is_same(decltype(v)....) stuff), but as you want to declare variables in the macro expansion, I think that's not helpful.
Another way you could use is to delay the expansion of first argument to later phase so you could overload it on number of arguments, like so:
// Add a comma. But later.
#define OUTCOME_REF(name) &&, name
#define OUTCOME_TRYA_CHOOSE_1(name, ...) \
auto unique0 = (__VA_ARGS__); name = std::move(unique0).value();
#define OUTCOME_TRYA_CHOOSE_2_IN(name, ...) \
auto &&unique1 = (__VA_ARGS__); name = std::move(unique1).value();
#define OUTCOME_TRYA_CHOOSE_2(name, ...) \
OUTCOME_TRYA_CHOOSE_2_IN(name __VA_ARGS__)
// ^^^^^^ I have no idea why it works without a comma, but it does. It's scary.
#define OUTCOME_TRYA_CHOOSE_N(_1,_2,N,...) \
OUTCOME_TRYA_CHOOSE_##N
#define OUTCOME_TRYA_CHOOSE(...) \
OUTCOME_TRYA_CHOOSE_N(__VA_ARGS__,2,1)
#define OUTCOME_TRYA(name, ...) \
OUTCOME_TRYA_CHOOSE(name)(name, __VA_ARGS__)
// ^^^^ - overload on number of arguments in expansion of first parameter
OUTCOME_TRYA(auto x, expr1) // auto unique0 = (expr1); auto x = std::move(unique0).value();
OUTCOME_TRYA(auto OUTCOME_REF(x), expr2) // auto &&unique1 = (expr2); auto && x = std::move(unique1).value();
In similar fashion you could refactor your interface seamlessly to:
#define UNPACK(...) __VA_ARGS__
#define OUTCOME_TRYA_CHOOSE_1(name, nameunpacked, ...) \
auto unique0 = (__VA_ARGS__); name = std::move(unique0).value();
#define OUTCOME_TRYA_CHOOSE_2_IN(name1, name2, ...) \
auto &&unique1 = (__VA_ARGS__); name1 name2 = std::move(unique1).value();
#define OUTCOME_TRYA_CHOOSE_2(name, nameunpacked, ...) \
OUTCOME_TRYA_CHOOSE_2_IN(nameunpacked, __VA_ARGS__)
#define OUTCOME_TRYA_CHOOSE_N(_1,_2,_3,N,...) \
OUTCOME_TRYA_CHOOSE_##N
#define OUTCOME_TRYA_CHOOSE(n, ...) \
OUTCOME_TRYA_CHOOSE_N(n, __VA_ARGS__, 2, 1)
#define OUTCOME_TRYA(name, ...) \
OUTCOME_TRYA_CHOOSE(name, UNPACK name)(name, UNPACK name, __VA_ARGS__)
OUTCOME_TRYA(auto x, expr1, expr2)
OUTCOME_TRYA((auto &&, x), expr3, expr4)
The above looks nice and allows for the current interface to stay. The trick is in OUTCOME_TRYA_CHOOSE(name, UNPACK name) - when name is (something, something), then OUTCOME_TRYA_CHOOSE_N is passed 3 arguments, if it's not, then 2 arguments are passed - which can be then overloaded on number of arguments. So it effectively overloads if the input contains braces with a comma inside.
I don't suppose you know of a way to achieve OUTCOME_TRYV((auto &&), expr1, expr2)
Meh ;p . Add a comma when unpacking, effectively shifting overloads to one more.
#define UNPACK_ADD_COMMA(...) ,__VA_ARGS__
#define OUTCOME_TRYA_CHOOSE_1(name, nameunpacked, ...) \
auto unique0 = (__VA_ARGS__); name = std::move(unique0).value();
#define OUTCOME_TRYA_CHOOSE_2_IN(name1, ...) \
OCH_MY_GOD()
#define OUTCOME_TRYA_CHOOSE_3_IN(name1, name2, ...) \
auto &&unique1 = (__VA_ARGS__); name1 name2 = std::move(unique1).value();
#define OUTCOME_TRYA_CHOOSE_2(name, nameunpacked, ...) \
OUTCOME_TRYA_CHOOSE_2_IN(nameunpacked, __VA_ARGS__)
#define OUTCOME_TRYA_CHOOSE_3(name, ignore, nameunpacked, ...) \
OUTCOME_TRYA_CHOOSE_3_IN(nameunpacked, __VA_ARGS__)
#define OUTCOME_TRYA_CHOOSE_N(_1,_2,_3,_4,N,...) \
OUTCOME_TRYA_CHOOSE_##N
#define OUTCOME_TRYA_CHOOSE_IN(n, ...) \
OUTCOME_TRYA_CHOOSE_N(n, __VA_ARGS__, 3, 2, 1)
#define OUTCOME_TRYA_CHOOSE(n, ...) \
OUTCOME_TRYA_CHOOSE_IN(n, __VA_ARGS__)
#define OUTCOME_TRYA(name, ...) \
OUTCOME_TRYA_CHOOSE(name, UNPACK_ADD_COMMA name)(name, UNPACK_ADD_COMMA name, __VA_ARGS__)
OUTCOME_TRYA(auto x, expr1, expr2)
OUTCOME_TRYA((auto &&, x), expr3, expr4)
OUTCOME_TRYA((auto &&), expr3, expr4)

Is it possible to use #define inside a function?

For example, I saw source code like the following. Can we use #define in a function? How does it work? (more information: this code is what I copied from openvswitch source code):
void *
ofputil_put_action(enum ofputil_action_code code, struct ofpbuf *buf)
{
switch (code) {
case OFPUTIL_ACTION_INVALID:
#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
#include "ofp-util.def"
OVS_NOT_REACHED();
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#include "ofp-util.def"
}
OVS_NOT_REACHED();
}
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \
void \
ofputil_init_##ENUM(struct STRUCT *s) \
{ \
memset(s, 0, sizeof *s); \
s->type = htons(ENUM); \
s->len = htons(sizeof *s); \
} \
\
struct STRUCT * \
ofputil_put_##ENUM(struct ofpbuf *buf) \
{ \
struct STRUCT *s = ofpbuf_put_uninit(buf, sizeof *s); \
ofputil_init_##ENUM(s); \
return s; \
}
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
OFPAT10_ACTION(ENUM, STRUCT, NAME)
#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
OFPAT10_ACTION(ENUM, STRUCT, NAME)
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
void \
ofputil_init_##ENUM(struct STRUCT *s) \
{ \
memset(s, 0, sizeof *s); \
s->type = htons(OFPAT10_VENDOR); \
s->len = htons(sizeof *s); \
s->vendor = htonl(NX_VENDOR_ID); \
s->subtype = htons(ENUM); \
} \
\
struct STRUCT * \
ofputil_put_##ENUM(struct ofpbuf *buf) \
{ \
struct STRUCT *s = ofpbuf_put_uninit(buf, sizeof *s); \
ofputil_init_##ENUM(s); \
return s; \
}
#include "ofp-util.def"
#define is a preprocessor directive: it is used to generate the eventual C++ code before it is handled to the compiler that will generate an executable. Therefore code like:
for(int i = 0; i < 54; i++) {
#define BUFFER_SIZE 1024
}
is not executed 54 times (at the preprocessor level): the preprocessor simply runs over the for loop (not knowing what a for loop is), sees a define statement, associates 1024 with BUFFER_SIZE and continues. Until it reaches the bottom of the file.
You can write #define everywhere since the preprocessor is not really aware of the program itself.
Sure this is possible. The #define is processed by the preprocessor before the compiler does anything. It is a simple text replacement. The preprocessor doesn't even know if the line of code is inside or outside a function, class or whatever.
By the way, it is generally considered bad style to define preprocessor macros in C++. Most of the things they are used for can be better achieved with templates.
You can use it inside a function, but it is not scoped to the function. So, in your example, the second definitions of a macro will be a redefinition and generate an error. You need to use #undef to clear them first.
You can use #define anywhere you want. It has no knowledge of functions and is not bound by their scope. As the preprocessor scans the file from top-to-bottom it processes #defines as it sees them. Do not be misled (by silly code like this!) into thinking that the #define is somehow processed only when the function is called; it's not.
How does it work? All C/C++ files are first processed by... the preprocessor.
It doesn't know anything about C nor C++ syntax. It simply replaces THIS_THING with ANOTHER THING. That's why you can place a #define in functions as well.
Sure. #define is handled by the preprocessor which occurs well before the compiler has any sense of lines of code being inside functions, inside parameters lists, inside data structures, etc.
Since the preprocessor has no concept of C++ functions, it also means that there is no natural scope to macro definitions. So if you want to reuse a macro name, you have to #undef NAME to avoid warnings.

How can I get the name of the macro-function?

I have the macro:
#define MYMACRO(pred, ...) \
pred /* here 'pred' is 'mypred(1, 2)', but I need to get only the name without args */
Which is used like this:
MYMACRO(mypred(1, 2))
I need to get only the name of the macro-function, without arguments.
I can do it like this:
#define mypred(...) \
mypred
#define MYMACRO_EXPAND(pred) \
pred /* here 'pred' is 'mypred' without args */
#define MYMACRO(pred, ...) \
MYMACRO_EXPAND(pred)
But this way is bad because I should define the macros for all possible macro-functions.
Ideas?
You could do it like this, but i do not recommend.
For example print the function name.
#define MYMACRO(func, ...) \
(printf("%s\n", #func), func(__VA_ARGS__))
And use it this way
MYMACRO(mypred, 1, 2);
or
int a = MYMACRO(pred, 1, 2);

Macro to return a unique string at compile-time

Is there a Macro that can return a unique-string at compile-time, so that it could be used as the name of an objective-c class?
I'm thinking of something like:
#define my_macro(params) \
#implementation my_macro_function_giving_unique_string_(MyTrickyRuntimeExtension) \
//Do stuff \
#end \
there is a macro __COUNTER__ predefined in Visual Studio that could help
I used iammilind suggestions
#define UNIQUE2(param) YourClassBaseNames##param
#define UNIQUE1(param) UNIQUE2(param)
#define UNIQUE UNIQUE1(__COUNTER__)
class UNIQUE
{
};
class UNIQUE
{
};
counter - returns new count ech time
reference: http://msdn.microsoft.com/en-us/library/b0084kay(v=vs.80).aspx
it is also available in GCC
In C++, it can be:
#define UNIQUE_NAME2(LINE) Class##LINE
#define UNIQUE_NAME1(LINE) UNIQUE_NAME2(LINE)
#define UNIQUE_NAME UNIQUE_NAME1(__LINE__)
And just use it as:
class UNIQUE_NAME {};
[Note: Declare 1 class per line and don't hope for forward declaring it anywhere :)]