Consider the following statements
typedef struct {
int member1;
int member2;
}Custom_t;
void ISR(void)
{
static Custom_t struct1[SOME_CONSTANT];
......
......
}
How can I initialize all member2 variable to a single value in C programming?
If I iniatilize the structure like the one shown below, then there is chance of somebody changing the "SOME_CONSTANT" in a header file and forgetting to update the list.
Another solution would be to give the structure a global scope for the current file. But the only function which uses the structure is the ISR().
void ISR(void)
{
static Custom_t struct1[SOME_CONSTANT] = {
{0, 3},
{0, 3},
......
......
};
......
......
}
Is there any method to solve this problem in C?
You can use Designated Initializers and do it in this way:
#include <stdio.h>
#define SOME_CONSTANT 30
typedef struct {
int member1;
int member2;
} Custom_t;
int main(void)
{
static Custom_t struct1[SOME_CONSTANT] =
{
[0 ... SOME_CONSTANT - 1].member2 = 30
};
printf("%d\n", struct1[25].member2);
printf("%d\n", struct1[19].member2);
printf("%d\n", struct1[0].member2);
return 0;
}
How about to add hard-coded compiling time checking against SOME_CONSTANT in the .c file (e.g. right before the initializer)?
#if SOME_CONSTANT != <some_hard_code_value>
#error "SOME_CONSTANT is not equal to <some_hard_code_value>"
#endif
The rational of this "hard-code" is whenever the SOME_CONSTANT is changed, the initializer need be updated, as well as the compiling time checking.
You don't need to specify the array size in advance, you can compute it later:
static Custom_t struct1[] = {
{0, 3},
{0, 3},
{13,3},
};
#define SOME_CONSTANT (sizeof struct1 /sizeof struct1[0])
or: use __LINE__ to compute the number of elements.
I've had to do something like this with projects with a configurable number of sensors :
[custom_t.h]
typedef struct {
int member1;
int member2;
}Custom_t;
#define MAX_CUSTOM_T 4
Custom_t *new_Custom_t (int member1, int member2);
[custom_t.c]
#include "custom_t.h"
static Custom_t g_Customt[MAX_CUSTOM_T];
static uint8 g_numCustom_t = 0;
Custom_t *new_Custom_t (int member1, int member2)
{
if ( g_numCustom_t < MAX_CUSTOM_T )
{
Custom_t *new_obj = &g_Customt[g_numCustom_t++];
new_obj->member1 = member1;
new_obj->member1 = member2;
return new_obj;
}
else
{
// throw exception?
// or go into while(1)?
// or software breakpoint if debug?
// or just...
return NULL;
}
}
[main.c]
#include "custom_t.h"
Custom_t *myCustom1;
Custom_t *myCustom2;
Custom_t *myCustom3;
somefunc()
{
myCustom1 = new_Custom_t (0,3);
myCustom2 = new_Custom_t (1,3);
myCustom3 = new_Custom_t (2,3);
// do stuff
}
It means if you want to create a new one, you may or may not need to update MAX_CUSTOM_T depending on its size already, but will just have to add a new line call to new_Custom_t(int,int). A Disadvantage though is it is slightly complex for what you might need, and if you ever want to add more members to initialize, you'll need to update the parameters passed into the new_ function to suit. This can be done instead with a sending a single separate structure for parameters rather than multiple parameters (a bit like MPLAB harmony).
I'm experimenting with memory management and trying to create something that will help with it in any way. Right now I'm trying to think is there any way to repeat the 'defer' functionality from Go in C.
Fast example for those who don't know what defer is:
package main
import "fmt"
func main() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
return
}
will print
3
2
1
So I'm thinking about some macros that will push the function with params to some stack and will call them when the function exit is called. Something like this:
int func(void)
{
MEMSTACK_INIT;
char * string = NULL;
node_t * node = NULL;
MEMSTACK_PUSH(free(string));
MEMSTACK_PUSH(NodeFree(&node));
<..>
switch (something)
{
case ONE : RETURN ERROR_ONE;
case TWO : RETURN ERROR_TWO;
case THR :
switch (something else)
{
<.. Many more code ..>
}
}
RETURN ERROR_GOOD;
}
Is there a way (except for making my own preprocessor, of course), to store somewhere a function call with params? In other words I want the previous code to be preprocessed in something like this:
int func(void)
{
<.. Some MEMSTACK initialisation stuff (if needed) ..>
char * string = NULL;
node_t * node = NULL;
<..>
switch (something)
{
case ONE :
free(string);
NodeFree(&node);
return ERROR_ONE;
case TWO :
free(string);
NodeFree(&node);
return ERROR_TWO;
case THR :
switch (something else)
{
<.. Many more code ..>
}
}
free(string);
NodeFree(&node);
return ERROR_GOOD;
}
It would be good thing for functions who require a lot of cleanup before exit.
Yes, yes, I know about goto cleanup trick.
I'm experimenting with memory management and trying to create something that will help with it in any way.
A good approach is to have only one return in any function. Possibly marked with a label (yes, so can gotoit, but this is also often discouraged). And of course: Be always sure to know who owns allocated memory and when (and where) ownership is transferred!
Now, let's...
[..] repeat the 'defer' functionality from Go in C.
First, in order to defer the call, we need to store the function (a pointer to it) as well as the evaluated arguments. Since C is statically typed, we need to unify that in a single type:
struct Fn {
void * parameters; // pointer to memory where the parameters are stored
void (*function)(void *); // pointer to function able to unpack parameters from above
struct Fn * next; // we want a stack, so ...
};
For each function that we are going to eventually defer, we need a way to store it's parameters. So we define a struct capable of holding the parameters and a function that is able to unpack the parameters from that struct:
#define MAKE_DEFERRABLE(name, N, ...) \
struct deferred_ ## name ## _parameters { PARAMS(N, __VA_ARGS__) }; \
void deferred_ ## name (void * p) { \
struct deferred_ ## name ## _parameters * parameters = p; \
printf(" -- Calling deferred " #name "\n"); \
(void)name(CPARAMS(N)); \
}
The N is the number of arguments. There are tricks to infer that from the __VA_ARGS__, but I'll leave that as an exercise for the reader. That macro contains two other macro expansions, PARAMS and CPARAMS. The former expands into a list suitable to define the struct contents. The later expands into code to extract the struct members as arguments:
#define PARAM_0(...)
#define PARAM_1(type, ...) type p1; PARAM_0(__VA_ARGS__)
#define PARAM_2(type, ...) type p2; PARAM_1(__VA_ARGS__)
#define PARAM_3(type, ...) type p3; PARAM_2(__VA_ARGS__)
#define PARAM_4(type, ...) type p4; PARAM_3(__VA_ARGS__)
#define PARAMS(N, ...) SPLICE(PARAM_, N)(__VA_ARGS__)
#define CPARAM_0
#define CPARAM_1 parameters->p1
#define CPARAM_2 parameters->p2, CPARAM_1
#define CPARAM_3 parameters->p3, CPARAM_2
#define CPARAM_4 parameters->p4, CPARAM_3
#define CPARAMS(N) SPLICE(CPARAM_, N)
If we'd want to defer functions with more than 4 parameters then this would need to be adjusted. The SPLICE is a nice little helper:
#define SPLICE_2(l,r) l##r
#define SPLICE_1(l,r) SPLICE_2(l,r)
#define SPLICE(l,r) SPLICE_1(l,r)
Next, we need to store the deferred functions somehow. For simplicity I choose to allocate them dynamically and keep a global pointer to the most recent:
struct Fn * deferred_fns = NULL;
Obviously you can extend this in many directions: Using (bounded) static storage, making it thread local, using per function deferred_fns, using alloca, ...
... but here's the simple, not production-ready (MISSING ERROR CHECKS) variant:
#define DEFER(name, N, ...) \
do { \
printf(" -- Deferring a call to " #name "\n"); \
if (deferred_fns == NULL) { \
deferred_fns = malloc(sizeof(*deferred_fns)); \
deferred_fns->next = NULL; \
} else { \
struct Fn * f = malloc(sizeof(*f)); \
f->next = deferred_fns; \
deferred_fns = f; \
} \
deferred_fns->function = &(deferred_ ## name); \
struct deferred_ ## name ##_parameters * parameters = malloc(sizeof(*parameters)); \
SPARAMS(N,__VA_ARGS__); \
deferred_fns->parameters = parameters; \
} while(0)
This just allocates a new struct Fn, makes it the top of the stack (read singly-linked list deferred_fns) and sets its members accordingly. The important SPARAMS saves the parameters into the corresponding struct:
#define SPARAM_0(...)
#define SPARAM_1(value, ...) parameters->p1 = (value); SPARAM_0(__VA_ARGS__)
#define SPARAM_2(value, ...) parameters->p2 = (value); SPARAM_1(__VA_ARGS__)
#define SPARAM_3(value, ...) parameters->p3 = (value); SPARAM_2(__VA_ARGS__)
#define SPARAM_4(value, ...) parameters->p4 = (value); SPARAM_3(__VA_ARGS__)
#define SPARAMS(N, ...) SPLICE(SPARAM_, N)(__VA_ARGS__)
Note: This fixes the order of parameter evaluation by making them evaluate from last to first. C does not mandate an evaluation order.
Finally, all that's left is a convenient way to run these deferred functions:
void run_deferred_fns(void) {
while (deferred_fns != NULL) {
deferred_fns->function(deferred_fns->parameters);
free(deferred_fns->parameters);
struct Fn * bye = deferred_fns;
deferred_fns = deferred_fns->next;
free(bye);
}
}
A small test:
void foo(int x) {
printf("foo: %d\n", x);
}
void bar(void) {
puts("bar");
}
void baz(int x, double y) {
printf("baz: %d %f\n", x, y);
}
MAKE_DEFERRABLE(foo, 1, int);
MAKE_DEFERRABLE(bar, 0);
MAKE_DEFERRABLE(baz, 2, int, double);
int main(void) {
DEFER(foo, 1, 42);
DEFER(bar, 0);
DEFER(foo, 1, 21);
DEFER(baz, 2, 42, 3.14);
run_deferred_fns();
return 0;
}
In order to achieve the same behavior as in your example, make deferred_fns a local variable, and pass that as parameter to run_deferred_fns. Wrap in simple macros, done:
#define PREPARE_DEFERRED_FNS struct Fn * deferred_fns = NULL;
#define RETURN(x) do { run_deferred_fns(deferred_fns); return (x); } while (0)
Welcome to insanity.
Note: My solution works at the "source level". By that I mean that you need to specify defer-able functions in the source code. That implies that you cannot, for example, defer a function loaded through dlopen. There's also a different approach, working at the ABI level, if you will: avcall, part of libffcall.
Now, I need really need my parentheses ... lots of them (())))(()(((()
I'm experimenting with using pre-processor macros to implement something like a templating engine in C, with the goal of allowing something like a typical MVC pattern. The application will probably be a simple static site generator with just the basic level of functionality that I can live with. The goal is mostly a learning experience, but I would also find it useful to have an SSG that both meets my needs and that I can completely understand.
I'm pretty pleased with how clean it seems to be turning out (clean being a relative term here, since I normally find macros to be anything but clean), but I'm not totally happy with how I'm handling collections. This amounts to what other frameworks call a repeater. The part that bothers me is that the controller has to know that the parent view consists of 3 sections: before the repeater, the repeater, and after the repeater. This could also apply to any views that need to reference multiple models (headers, navbars, etc.). Is there an established way of encapsulating this in C? Can it be done? Should it be done?
Here's the gist of what I've done:
/*tag.h*/
#ifndef TAG_H
#define TAG_H
#define tag(name,children) "<" name ">" children "</" name ">"
#define stag(name,attrs) "<" name " " attrs ">"
#define etag(name) "</" name ">"
#endif
/*child_model.h*/
#ifndef CHILD_MODEL_H
#define CHILD_MODEL_H
struct child
{
char *detail;
};
#endif
/*child_view.h*/
#ifndef CHILD_VIEW_H
#define CHILD_VIEW_H
#include "tag.h"
#include "child_model.h"
#define child_view(m) \
tag("li", "%s"),\
(m).detail\
#endif
/*parent_model.h*/
#ifndef PARENT_MODEL_H
#define PARENT_MODEL_H
struct parent
{
char *title;
char *subtitle;
};
#endif
/*parent_view.h*/
#ifndef PARENT_VIEW_H
#define PARENT_VIEW_H
#include "tag.h"
#include "parent_model.h"
#define parent_view_s1(m) \
stag("html","")\
tag("head",\
tag("title", "%s")\
)\
stag("body","")\
tag("h1", "%s")\
tag("p", "%s")\
stag("ul",""),\
(m).title,\
(m).title,\
(m).subtitle\
#define parent_view_s2(m) \
etag("ul")\
etag("body")\
etag("html")\
#endif
/*controller.c*/
#include "parent_model.h"
#include "parent_view.h"
#include "child_model.h"
#include "child_view.h"
int
example_controller(int (*render)(void *, const char *, ...), void *render_ctx, struct parent *p, struct child *chlist, int n)
{
int i;
int e;
/*render, here, is effectively like fprintf: render_ctx holds the stream information, and the view macro expands to the format string and args*/
e = render(render_ctx, parent_view_s1(*p));
if(e < 0) return e;
for(i = 0; i < n; i++)
{
e = render(render_ctx, child_view(chlist[i]));
if(e < 0) return e;
}
e = render(render_ctx, parent_view_s2(*p));
if(e < 0) return e;
return 0;
}
Here's what I am trying to do:
typedef enum { ONE, TWO, THREE } Numbers;
I am trying to write a function that would do a switch case similar to the following:
char num_str[10];
int process_numbers_str(Numbers num) {
switch(num) {
case ONE:
case TWO:
case THREE:
{
strcpy(num_str, num); //some way to get the symbolic constant name in here?
} break;
default:
return 0; //no match
return 1;
}
Instead of defining at every case, is there a way to set it using the enum variable like I am trying to do above?
The technique from Making something both a C identifier and a string? can be used here.
As usual with such preprocessor stuff, writing and understanding the preprocessor part can be hard, and includes passing macros to other macros and involves using # and ## operators, but using it is real easy. I find this style very useful for long enums, where maintaining the same list twice can be really troublesome.
Factory code - typed only once, usually hidden in the header:
enumFactory.h:
// expansion macro for enum value definition
#define ENUM_VALUE(name,assign) name assign,
// expansion macro for enum to string conversion
#define ENUM_CASE(name,assign) case name: return #name;
// expansion macro for string to enum conversion
#define ENUM_STRCMP(name,assign) if (!strcmp(str,#name)) return name;
/// declare the access function and define enum values
#define DECLARE_ENUM(EnumType,ENUM_DEF) \
enum EnumType { \
ENUM_DEF(ENUM_VALUE) \
}; \
const char *GetString(EnumType dummy); \
EnumType Get##EnumType##Value(const char *string); \
/// define the access function names
#define DEFINE_ENUM(EnumType,ENUM_DEF) \
const char *GetString(EnumType value) \
{ \
switch(value) \
{ \
ENUM_DEF(ENUM_CASE) \
default: return ""; /* handle input error */ \
} \
} \
EnumType Get##EnumType##Value(const char *str) \
{ \
ENUM_DEF(ENUM_STRCMP) \
return (EnumType)0; /* handle input error */ \
} \
Factory used
someEnum.h:
#include "enumFactory.h"
#define SOME_ENUM(XX) \
XX(FirstValue,) \
XX(SecondValue,) \
XX(SomeOtherValue,=50) \
XX(OneMoreValue,=100) \
DECLARE_ENUM(SomeEnum,SOME_ENUM)
someEnum.cpp:
#include "someEnum.h"
DEFINE_ENUM(SomeEnum,SOME_ENUM)
The technique can be easily extended so that XX macros accepts more arguments, and you can also have prepared more macros to substitute for XX for different needs, similar to the three I have provided in this sample.
Comparison to X-Macros using #include / #define / #undef
While this is similar to X-Macros others have mentioned, I think this solution is more elegant in that it does not require #undefing anything, which allows you to hide more of the complicated stuff is in the factory the header file - the header file is something you are not touching at all when you need to define a new enum, therefore new enum definition is a lot shorter and cleaner.
// Define your enumeration like this (in say numbers.h);
ENUM_BEGIN( Numbers )
ENUM(ONE),
ENUM(TWO),
ENUM(FOUR)
ENUM_END( Numbers )
// The macros are defined in a more fundamental .h file (say defs.h);
#define ENUM_BEGIN(typ) enum typ {
#define ENUM(nam) nam
#define ENUM_END(typ) };
// Now in one and only one .c file, redefine the ENUM macros and reinclude
// the numbers.h file to build a string table
#undef ENUM_BEGIN
#undef ENUM
#undef ENUM_END
#define ENUM_BEGIN(typ) const char * typ ## _name_table [] = {
#define ENUM(nam) #nam
#define ENUM_END(typ) };
#undef NUMBERS_H_INCLUDED // whatever you need to do to enable reinclusion
#include "numbers.h"
// Now you can do exactly what you want to do, with no retyping, and for any
// number of enumerated types defined with the ENUM macro family
// Your code follows;
char num_str[10];
int process_numbers_str(Numbers num) {
switch(num) {
case ONE:
case TWO:
case THREE:
{
strcpy(num_str, Numbers_name_table[num]); // eg TWO -> "TWO"
} break;
default:
return 0; //no match
return 1;
}
// Sweet no ? After being frustrated by this for years, I finally came up
// with this solution for my most recent project and plan to reuse the idea
// forever
There's no built-in solution. The easiest way is with an array of char* where the enum's int value indexes to a string containing the descriptive name of that enum. If you have a sparse enum (one that doesn't start at 0 or has gaps in the numbering) where some of the int mappings are high enough to make an array-based mapping impractical then you could use a hash table instead.
There is definitely a way to do this -- use X() macros. These macros use the C preprocessor to construct enums, arrays and code blocks from a list of source data. You only need to add new items to the #define containing the X() macro. The switch statement would expand automatically.
Your example can be written as follows:
// Source data -- Enum, String
#define X_NUMBERS \
X(ONE, "one") \
X(TWO, "two") \
X(THREE, "three")
...
// Use preprocessor to create the Enum
typedef enum {
#define X(Enum, String) Enum,
X_NUMBERS
#undef X
} Numbers;
...
// Use Preprocessor to expand data into switch statement cases
switch(num)
{
#define X(Enum, String) \
case Enum: strcpy(num_str, String); break;
X_NUMBERS
#undef X
default: return 0; break;
}
return 1;
There are more efficient ways (i.e. using X Macros to create an string array and enum index), but this is the simplest demo.
I know you have a couple good solid answers, but do you know about the # operator in the C preprocessor?
It lets you do this:
#define MACROSTR(k) #k
typedef enum {
kZero,
kOne,
kTwo,
kThree
} kConst;
static char *kConstStr[] = {
MACROSTR(kZero),
MACROSTR(kOne),
MACROSTR(kTwo),
MACROSTR(kThree)
};
static void kConstPrinter(kConst k)
{
printf("%s", kConstStr[k]);
}
C or C++ does not provide this functionality, although I've needed it often.
The following code works, although it's best suited for non-sparse enums.
typedef enum { ONE, TWO, THREE } Numbers;
char *strNumbers[] = {"one","two","three"};
printf ("Value for TWO is %s\n",strNumbers[TWO]);
By non-sparse, I mean not of the form
typedef enum { ONE, FOUR_THOUSAND = 4000 } Numbers;
since that has huge gaps in it.
The advantage of this method is that it put the definitions of the enums and strings near each other; having a switch statement in a function spearates them. This means you're less likely to change one without the other.
KISS. You will be doing all sorts of other switch/case things with your enums so why should printing be different? Forgetting a case in your print routine isn't a huge deal when you consider there are about 100 other places you can forget a case. Just compile -Wall, which will warn of non-exhaustive case matches. Don't use "default" because that will make the switch exhaustive and you wont get warnings. Instead, let the switch exit and deal with the default case like so...
const char *myenum_str(myenum e)
{
switch(e) {
case ONE: return "one";
case TWO: return "two";
}
return "invalid";
}
Try Converting C++ enums to strings. The comments have improvements that solve the problem when enum items have arbitrary values.
The use of boost::preprocessor makes possible an elegant solution like the following:
Step 1: include the header file:
#include "EnumUtilities.h"
Step 2: declare the enumeration object with the following syntax:
MakeEnum( TestData,
(x)
(y)
(z)
);
Step 3: use your data:
Getting the number of elements:
td::cout << "Number of Elements: " << TestDataCount << std::endl;
Getting the associated string:
std::cout << "Value of " << TestData2String(x) << " is " << x << std::endl;
std::cout << "Value of " << TestData2String(y) << " is " << y << std::endl;
std::cout << "Value of " << TestData2String(z) << " is " << z << std::endl;
Getting the enum value from the associated string:
std::cout << "Value of x is " << TestData2Enum("x") << std::endl;
std::cout << "Value of y is " << TestData2Enum("y") << std::endl;
std::cout << "Value of z is " << TestData2Enum("z") << std::endl;
This looks clean and compact, with no extra files to include.
The code I wrote within EnumUtilities.h is the following:
#include <boost/preprocessor/seq/for_each.hpp>
#include <string>
#define REALLY_MAKE_STRING(x) #x
#define MAKE_STRING(x) REALLY_MAKE_STRING(x)
#define MACRO1(r, data, elem) elem,
#define MACRO1_STRING(r, data, elem) case elem: return REALLY_MAKE_STRING(elem);
#define MACRO1_ENUM(r, data, elem) if (REALLY_MAKE_STRING(elem) == eStrEl) return elem;
#define MakeEnum(eName, SEQ) \
enum eName { BOOST_PP_SEQ_FOR_EACH(MACRO1, , SEQ) \
last_##eName##_enum}; \
const int eName##Count = BOOST_PP_SEQ_SIZE(SEQ); \
static std::string eName##2String(const enum eName eel) \
{ \
switch (eel) \
{ \
BOOST_PP_SEQ_FOR_EACH(MACRO1_STRING, , SEQ) \
default: return "Unknown enumerator value."; \
}; \
}; \
static enum eName eName##2Enum(const std::string eStrEl) \
{ \
BOOST_PP_SEQ_FOR_EACH(MACRO1_ENUM, , SEQ) \
return (enum eName)0; \
};
There are some limitation, i.e. the ones of boost::preprocessor. In this case, the list of constants cannot be larger than 64 elements.
Following the same logic, you could also think to create sparse enum:
#define EnumName(Tuple) BOOST_PP_TUPLE_ELEM(2, 0, Tuple)
#define EnumValue(Tuple) BOOST_PP_TUPLE_ELEM(2, 1, Tuple)
#define MACRO2(r, data, elem) EnumName(elem) EnumValue(elem),
#define MACRO2_STRING(r, data, elem) case EnumName(elem): return BOOST_PP_STRINGIZE(EnumName(elem));
#define MakeEnumEx(eName, SEQ) \
enum eName { \
BOOST_PP_SEQ_FOR_EACH(MACRO2, _, SEQ) \
last_##eName##_enum }; \
const int eName##Count = BOOST_PP_SEQ_SIZE(SEQ); \
static std::string eName##2String(const enum eName eel) \
{ \
switch (eel) \
{ \
BOOST_PP_SEQ_FOR_EACH(MACRO2_STRING, _, SEQ) \
default: return "Unknown enumerator value."; \
}; \
};
In this case, the syntax is:
MakeEnumEx(TestEnum,
((x,))
((y,=1000))
((z,))
);
Usage is similar as above (minus the eName##2Enum function, that you could try to extrapolate from the previous syntax).
I tested it on mac and linux, but be aware that boost::preprocessor may not be fully portable.
By merging some of the techniques over here I came up with the simplest form:
#define MACROSTR(k) #k
#define X_NUMBERS \
X(kZero ) \
X(kOne ) \
X(kTwo ) \
X(kThree ) \
X(kFour ) \
X(kMax )
enum {
#define X(Enum) Enum,
X_NUMBERS
#undef X
} kConst;
static char *kConstStr[] = {
#define X(String) MACROSTR(String),
X_NUMBERS
#undef X
};
int main(void)
{
int k;
printf("Hello World!\n\n");
for (k = 0; k < kMax; k++)
{
printf("%s\n", kConstStr[k]);
}
return 0;
}
If you are using gcc, it's possible to use:
const char * enum_to_string_map[]={ [enum1]='string1', [enum2]='string2'};
Then just call for instance
enum_to_string_map[enum1]
Check out the ideas at Mu Dynamics Research Labs - Blog Archive. I found this earlier this year - I forget the exact context where I came across it - and have adapted it into this code. We can debate the merits of adding an E at the front; it is applicable to the specific problem addressed, but not part of a general solution. I stashed this away in my 'vignettes' folder - where I keep interesting scraps of code in case I want them later. I'm embarrassed to say that I didn't keep a note of where this idea came from at the time.
Header: paste1.h
/*
#(#)File: $RCSfile: paste1.h,v $
#(#)Version: $Revision: 1.1 $
#(#)Last changed: $Date: 2008/05/17 21:38:05 $
#(#)Purpose: Automated Token Pasting
*/
#ifndef JLSS_ID_PASTE_H
#define JLSS_ID_PASTE_H
/*
* Common case when someone just includes this file. In this case,
* they just get the various E* tokens as good old enums.
*/
#if !defined(ETYPE)
#define ETYPE(val, desc) E##val,
#define ETYPE_ENUM
enum {
#endif /* ETYPE */
ETYPE(PERM, "Operation not permitted")
ETYPE(NOENT, "No such file or directory")
ETYPE(SRCH, "No such process")
ETYPE(INTR, "Interrupted system call")
ETYPE(IO, "I/O error")
ETYPE(NXIO, "No such device or address")
ETYPE(2BIG, "Arg list too long")
/*
* Close up the enum block in the common case of someone including
* this file.
*/
#if defined(ETYPE_ENUM)
#undef ETYPE_ENUM
#undef ETYPE
ETYPE_MAX
};
#endif /* ETYPE_ENUM */
#endif /* JLSS_ID_PASTE_H */
Example source:
/*
#(#)File: $RCSfile: paste1.c,v $
#(#)Version: $Revision: 1.2 $
#(#)Last changed: $Date: 2008/06/24 01:03:38 $
#(#)Purpose: Automated Token Pasting
*/
#include "paste1.h"
static const char *sys_errlist_internal[] = {
#undef JLSS_ID_PASTE_H
#define ETYPE(val, desc) desc,
#include "paste1.h"
0
#undef ETYPE
};
static const char *xerror(int err)
{
if (err >= ETYPE_MAX || err <= 0)
return "Unknown error";
return sys_errlist_internal[err];
}
static const char*errlist_mnemonics[] = {
#undef JLSS_ID_PASTE_H
#define ETYPE(val, desc) [E ## val] = "E" #val,
#include "paste1.h"
#undef ETYPE
};
#include <stdio.h>
int main(void)
{
int i;
for (i = 0; i < ETYPE_MAX; i++)
{
printf("%d: %-6s: %s\n", i, errlist_mnemonics[i], xerror(i));
}
return(0);
}
Not necessarily the world's cleanest use of the C pre-processor - but it does prevent writing the material out multiple times.
Making something both a C identifier and a string
#define stringify( name ) # name
enum MyEnum {
ENUMVAL1
};
...stuff...
stringify(EnumName::ENUMVAL1); // Returns MyEnum::ENUMVAL1
Further discussion on this method
Preprocessor directive tricks for newcomers
If the enum index is 0-based, you can put the names in an array of char*, and index them with the enum value.
I have created a simple templated class streamable_enum that uses stream operators << and >> and is based on the std::map<Enum, std::string>:
#ifndef STREAMABLE_ENUM_HPP
#define STREAMABLE_ENUM_HPP
#include <iostream>
#include <string>
#include <map>
template <typename E>
class streamable_enum
{
public:
typedef typename std::map<E, std::string> tostr_map_t;
typedef typename std::map<std::string, E> fromstr_map_t;
streamable_enum()
{}
streamable_enum(E val) :
Val_(val)
{}
operator E() {
return Val_;
}
bool operator==(const streamable_enum<E>& e) {
return this->Val_ == e.Val_;
}
bool operator==(const E& e) {
return this->Val_ == e;
}
static const tostr_map_t& to_string_map() {
static tostr_map_t to_str_(get_enum_strings<E>());
return to_str_;
}
static const fromstr_map_t& from_string_map() {
static fromstr_map_t from_str_(reverse_map(to_string_map()));
return from_str_;
}
private:
E Val_;
static fromstr_map_t reverse_map(const tostr_map_t& eToS) {
fromstr_map_t sToE;
for (auto pr : eToS) {
sToE.emplace(pr.second, pr.first);
}
return sToE;
}
};
template <typename E>
streamable_enum<E> stream_enum(E e) {
return streamable_enum<E>(e);
}
template <typename E>
typename streamable_enum<E>::tostr_map_t get_enum_strings() {
// \todo throw an appropriate exception or display compile error/warning
return {};
}
template <typename E>
std::ostream& operator<<(std::ostream& os, streamable_enum<E> e) {
auto& mp = streamable_enum<E>::to_string_map();
auto res = mp.find(e);
if (res != mp.end()) {
os << res->second;
} else {
os.setstate(std::ios_base::failbit);
}
return os;
}
template <typename E>
std::istream& operator>>(std::istream& is, streamable_enum<E>& e) {
std::string str;
is >> str;
if (str.empty()) {
is.setstate(std::ios_base::failbit);
}
auto& mp = streamable_enum<E>::from_string_map();
auto res = mp.find(str);
if (res != mp.end()) {
e = res->second;
} else {
is.setstate(std::ios_base::failbit);
}
return is;
}
#endif
Usage:
#include "streamable_enum.hpp"
using std::cout;
using std::cin;
using std::endl;
enum Animal {
CAT,
DOG,
TIGER,
RABBIT
};
template <>
streamable_enum<Animal>::tostr_map_t get_enum_strings<Animal>() {
return {
{ CAT, "Cat"},
{ DOG, "Dog" },
{ TIGER, "Tiger" },
{ RABBIT, "Rabbit" }
};
}
int main(int argc, char* argv []) {
cout << "What animal do you want to buy? Our offering:" << endl;
for (auto pr : streamable_enum<Animal>::to_string_map()) { // Use from_string_map() and pr.first instead
cout << " " << pr.second << endl; // to have them sorted in alphabetical order
}
streamable_enum<Animal> anim;
cin >> anim;
if (!cin) {
cout << "We don't have such animal here." << endl;
} else if (anim == Animal::TIGER) {
cout << stream_enum(Animal::TIGER) << " was a joke..." << endl;
} else {
cout << "Here you are!" << endl;
}
return 0;
}
Here is a solution using macros with the following features:
only write each value of the enum once, so there are no double lists to maintain
don't keep the enum values in a separate file that is later #included, so I can write it wherever I want
don't replace the enum itself, I still want to have the enum type defined, but in addition to it I want to be able to map every enum name to the corresponding string (to not affect legacy code)
the searching should be fast, so preferably no switch-case, for those huge enums
https://stackoverflow.com/a/20134475/1812866
I thought that a solution like Boost.Fusion one for adapting structs and classes would be nice, they even had it at some point, to use enums as a fusion sequence.
So I made just some small macros to generate the code to print the enums. This is not perfect and has nothing to see with Boost.Fusion generated boilerplate code, but can be used like the Boost Fusion macros. I want to really do generate the types needed by Boost.Fusion to integrate in this infrastructure which allows to print names of struct members, but this will happen later, for now this is just macros :
#ifndef SWISSARMYKNIFE_ENUMS_ADAPT_ENUM_HPP
#define SWISSARMYKNIFE_ENUMS_ADAPT_ENUM_HPP
#include <swissarmyknife/detail/config.hpp>
#include <string>
#include <ostream>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#define SWISSARMYKNIFE_ADAPT_ENUM_EACH_ENUMERATION_ENTRY_C( \
R, unused, ENUMERATION_ENTRY) \
case ENUMERATION_ENTRY: \
return BOOST_PP_STRINGIZE(ENUMERATION_ENTRY); \
break;
/**
* \brief Adapts ENUM to reflectable types.
*
* \param ENUM_TYPE To be adapted
* \param ENUMERATION_SEQ Sequence of enum states
*/
#define SWISSARMYKNIFE_ADAPT_ENUM(ENUM_TYPE, ENUMERATION_SEQ) \
inline std::string to_string(const ENUM_TYPE& enum_value) { \
switch (enum_value) { \
BOOST_PP_SEQ_FOR_EACH( \
SWISSARMYKNIFE_ADAPT_ENUM_EACH_ENUMERATION_ENTRY_C, \
unused, ENUMERATION_SEQ) \
default: \
return BOOST_PP_STRINGIZE(ENUM_TYPE); \
} \
} \
\
inline std::ostream& operator<<(std::ostream& os, const ENUM_TYPE& value) { \
os << to_string(value); \
return os; \
}
#endif
The old answer below is pretty bad, please don't use that. :)
Old answer:
I've been searching a way which solves this problem without changing too much the enums declaration syntax. I came to a solution which uses the preprocessor to retrieve a string from a stringified enum declaration.
I'm able to define non-sparse enums like this :
SMART_ENUM(State,
enum State {
RUNNING,
SLEEPING,
FAULT,
UNKNOWN
})
And I can interact with them in different ways:
// With a stringstream
std::stringstream ss;
ss << State::FAULT;
std::string myEnumStr = ss.str();
//Directly to stdout
std::cout << State::FAULT << std::endl;
//to a string
std::string myStr = State::to_string(State::FAULT);
//from a string
State::State myEnumVal = State::from_string(State::FAULT);
Based on the following definitions :
#define SMART_ENUM(enumTypeArg, ...) \
namespace enumTypeArg { \
__VA_ARGS__; \
std::ostream& operator<<(std::ostream& os, const enumTypeArg& val) { \
os << swissarmyknife::enums::to_string(#__VA_ARGS__, val); \
return os; \
} \
\
std::string to_string(const enumTypeArg& val) { \
return swissarmyknife::enums::to_string(#__VA_ARGS__, val); \
} \
\
enumTypeArg from_string(const std::string &str) { \
return swissarmyknife::enums::from_string<enumTypeArg>(#__VA_ARGS__, str); \
} \
} \
namespace swissarmyknife { namespace enums {
static inline std::string to_string(const std::string completeEnumDeclaration, size_t enumVal) throw (std::runtime_error) {
size_t begin = completeEnumDeclaration.find_first_of('{');
size_t end = completeEnumDeclaration.find_last_of('}');
const std::string identifiers = completeEnumDeclaration.substr(begin + 1, end );
size_t count = 0;
size_t found = 0;
do {
found = identifiers.find_first_of(",}", found+1);
if (enumVal == count) {
std::string identifiersSubset = identifiers.substr(0, found);
size_t beginId = identifiersSubset.find_last_of("{,");
identifiersSubset = identifiersSubset.substr(beginId+1);
boost::algorithm::trim(identifiersSubset);
return identifiersSubset;
}
++count;
} while (found != std::string::npos);
throw std::runtime_error("The enum declaration provided doesn't contains this state.");
}
template <typename EnumType>
static inline EnumType from_string(const std::string completeEnumDeclaration, const std::string &enumStr) throw (std::runtime_error) {
size_t begin = completeEnumDeclaration.find_first_of('{');
size_t end = completeEnumDeclaration.find_last_of('}');
const std::string identifiers = completeEnumDeclaration.substr(begin + 1, end );
size_t count = 0;
size_t found = 0;
do {
found = identifiers.find_first_of(",}", found+1);
std::string identifiersSubset = identifiers.substr(0, found);
size_t beginId = identifiersSubset.find_last_of("{,");
identifiersSubset = identifiersSubset.substr(beginId+1);
boost::algorithm::trim(identifiersSubset);
if (identifiersSubset == enumStr) {
return static_cast<EnumType>(count);
}
++count;
} while (found != std::string::npos);
throw std::runtime_error("No valid enum value for the provided string");
}
}}
When I'll need support for sparse enum and when I'll have more time I'll improve the to_string and from_string implementations with boost::xpressive, but this will costs in compilation time because of the important templating performed and the executable generated is likely to be really bigger. But this has the advantage that it will be more readable and maintanable than this ugly manual string manipulation code. :D
Otherwise I always used boost::bimap to perform such mappings between enums value and string, but it has to be maintained manually.
Because I prefer not to use macros for all the usual reasons, I used a more limited macro solution that has the advantage of keeping the enum declaration macro free. Disadvantages include having to copy paste the macro defintion for each enum, and having to explicitly add a macro invocation when adding values to the enum.
std::ostream& operator<<(std::ostream& os, provenance_wrapper::CaptureState cs)
{
#define HANDLE(x) case x: os << #x; break;
switch (cs) {
HANDLE(CaptureState::UNUSED)
HANDLE(CaptureState::ACTIVE)
HANDLE(CaptureState::CLOSED)
}
return os;
#undef HANDLE
}
There's a way simpler and imo sorta clearer approach
that was missing on this thread:
#define ENUM_PUSH(ENUM) ENUM,
#define STRING_PUSH(STR) #STR,
#define FETCH_MSG(X) \
X(string1) \
X(string2) \
static const char * msgStr[] = {
FETCH_MSG(STRING_PUSH)
};
enum msg {
FETCH_MSG(ENUM_PUSH)
};
static enum msg message;
void iterate(void) {
switch (message) {
case string1:
// do your thing here
break;
case string2:
break;
}
}
The only downside is that the last cell will be postceded by a comma,
though it appears to be acceptable by C/C++ compilers.