Generic method to display enum value names - c++

Is there a way to display the name of an enum's value?
say we have:
enum fuits{
APPLE,
MANGO,
ORANGE,
};
main(){
enum fruits xFruit = MANGO;
...
printf("%s",_PRINT_ENUM_STRING(xFruit));
...
}
using the preprocessor
#define _PRINT_ENUM_STRING(x) #x
won't work as we need to get the value of the variable 'x' and then convert It to string.
Is this at all possible in c/C++?

You could use the preprocessor to do this, I believe this technique is called X-Macros:
/* fruits.def */
X(APPLE)
X(MANGO)
X(ORANGE)
/* file.c */
enum fruits {
#define X(a) a,
#include "fruits.def"
#undef X
};
const char *fruit_name[] = {
#define X(a) #a,
#include "fruits.def"
#undef X
};
Note that the last entry includes a trailing comma, which is allowed in C99 (but not in C89). If that is a problem you can add sentinal values. It is also possible to make the macro more complicated by giving multiple arguments for custom names or enum values, etc:
X(APPLE, Apple, 2)
#define X(a,b,c) a = c, /* in enum */
#define X(a,b,c) [c] = #b, /* in name array */
Limitations: You cannot have negative constants and your array is sizeof (char *) * largest_constant. But you could work around both by using an extra lookup table:
int map[] = {
#define X(a,b,c) c,
#include "fruits.def"
#undef X
};
This doesn't work of course. What does work is generating an extra set of enum constants as keys for the names:
enum fruits {
#define X(a,b,c) a ## _KEY,
#include "fruits.def"
#undef X
#define X(a,b,c) a = c,
#include "fruits.def"
#undef X
};
Now you can find the name of X(PINEAPPLE, Pineapple, -40) by using fruit_name[PINEAPPLE_KEY].
People noted that they didn't like the extra include file. You don't need this extra file, you also use a #define. This may be more appropriate for small lists:
#define FRUIT_LIST X(APPLE) X(ORANGE)
And replace #include "fruits.def with FRUIT_LIST in the previous examples.

You can use a mapping in this case.
char *a[10] = { "APPLE","MANGO","ORANGE"};
printf("%s",a[xFruit]);
Yes the preprocessor won't work unless you provide the exact enum -value.
Also check this question for more insights.

I've used preprocessor programming successfully to get a macro of this kind:
DEFINE_ENUM(Fruits, (Apple)(Mango)(Orange));
It does a tad more than just printing the names, but it could easily be simplified to 2 switches if necessary.
It's based on Boost.Preprocessor facilities (notably BOOST_PP_SEQ_FOREACH) which is a must have for preprocessor programming, and I find it much more elegant than the X facility and its file reinclusion system.

public enum LDGoalProgressUpdateState
{
[Description("Yet To Start")]
YetToStart = 1,
[Description("In Progress")]
InProgress = 2,
[Description("Completed")]
Completed = 3
}
var values = (ENUMList[])Enum.GetValues(typeof(ENUMList));
var query = from name in values
select new EnumData//EnumData is a Modal or Entity
{
ID = (short)name,
Name = GetEnumDescription(name)//Description of Particular Enum Name
};
return query.ToList();
region HelperMethods
public static string GetEnumDescription(Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0)
return attributes[0].Description;
else
return value.ToString();
}
#endregion

Related

C or C++ preprocessor selecting code blocks

I'm trying to write a production test software for an embedded system where I could write a single test script (which ideally is just C++ code), where parts are executed on the host computer and part on the DUT (Device Under Test). Communication is through a serial port.
One important goal here is to reduce code size on the embedded side, without reducing readability of the test output. So my level 0 objective, you could say a warmup exercise, is to be able to write something like this:
//TestScript.cpp
START_TESTS()
...
const unsigned pot1res = testPotentiometer(pot1);
TEST_PRINT("Potentiometer 1 test result %u", pot1res);
const unsigned pot2res = testPotentiometer(pot2);
TEST_PRINT("Potentiometer 2 test result %u", pot2res);
...
END_TESTS()
which would compile through preprocessor trickery and selective compilation on the embedded side to
const unsigned pot1res = testPotentiometer(pot1);
write_uart(123); //Unique id, perhaps from __COUNTER__
write_uart(pot1res);
const unsigned pot2res = testPotentiometer(pot2);
write_uart(124); //Unique id, perhaps from __COUNTER__
write_uart(pot2res);
and on the host
std::array gTestStrings = {
... other strings ....
TestString{123, "Potentiometer 1 test result %u", unsigned_tag},
TestString{124, "Potentiometer 2 test result %u", unsigned_tag},
... more strings ....
};
The purpose of the latter is then of course that the host software simply listens to the UART for the unique id's, then looks up the needed parameters from gTestStrings, receives them, and prints out the message to its test log. Note that the strings have disappeared entirely from the embedded side.
The embedded side here is of course easy, just define the TEST_PRINT macro in the obvious way, and supporting varargs etc shouldn't be too difficult. However, it's not clear how define the host side, since the code in between the macros has to disappear entirely. I'm pretty sure I can deal with getting the unsigned_tags etc correctly with some templates etc.
Standard C++17 is appreciated, but GCC/Clang specifics are allowed if needed, the preprocessor will obviously play heavily into this etc. The syntax of the macros can of course also be adjusted where necessary.
On the basis of "use templates to do the same thing with different types" you could simply define a templated class or method which invoke different implementations according to whether in the embedded context or host context.
Pseudocode example:
#include <sstream>
#include <string>
class Mock
{
protected:
// TODO : output values array / map - by - testID
public:
unsigned readPot(int const testID)
{
// TODO : return value from the values array/map
}
};
class ActualDevice
{
public:
unsigned readPot(int const testID)
{
// TODO : write/read the device
}
};
//DEVICE_IMPL must implement a method with this signature:
//unsigned readPot(int const testID)
template<typename DEVICE_IMPL>
void runTests()
{
DEVICE_IMPL device;
std::string testOutput;
//TODO : substitute with for-loop to run all tests
int testID = 1;
{
unsigned output = device.readPot(testID);
std::stringstream accum;
accum << "Test " << testID << " output = " << (int)output << std::endl;
testOutput = accum.str();
// TODO : do something with testOutput
}
}
void testHost ()
{
runTests<Mock>();
}
void testDevice()
{
runTests<ActualDevice>();
}
#ifdef __linux__ // or whatever you have there
#define START_TESTS() std::array gTestStrings = {
#define END_TESTS() };
#define TEST(expr, str) TestString{__LINE__, str, unsigned_tag},
#else
#define START_TESTS() {
#define END_TESTS() }
#define TEST(expr, ...) do{ \
const auto _val = (expr); \
write_uart(__LINE__); \
write_uart(_val); \
} while(0)
#endif
int main() {
START_TESTS()
TEST(testPotentiometer(pot1), "Potentiometer 1 test result %u");
TEST(testPotentiometer(pot2), "Potentiometer 2 test result %u");
END_TESTS()
}
I do not particularly like that design - seems not flexible enough for me. But such code could serve as a template for you to write something better. I added the expression inside the TEST macro - that way it can be removed on the host side, and used on the device side.
Another option could be X-macros:
pot_tests.h
X(123, pot1, "Potentiometer 1 test result %u")
X(124, pot2, "Potentiometer 2 test result %u")
embedded.c
START_TESTS()
...
#define X(id, pot, text) \
do { \
const unsigned potres = testPotentiometer(pot); \
write_uart(id); \
write_uart(potres); \
TEST_PRINT(text, potres); \
} while(0);
#include "pot_tests.h"
#undef X
...
END_TESTS()
host.cpp
std::array gTestStrings = {
... other strings ....
#define X(id, pot, text) TestString{id, text, unsigned_tag},
#include "pot_tests.h"
#undef X
... more strings ....
};

How can I get full, expanded, stringified macros from boost::wave?

I have a file containing the following:
#define str(s) s
#define xstr(s) #s
#define foo 4
#define first str(foo)
#define second xstr(foo)
When I pass this into boost::wave, the macromap contains the following:
first=str(foo)
foo=4
second=xstr(foo)
str(s)=#s
xstr(s)=str(s)
How can I get the macros to be fully expanded such that:
first="foo"
second=4
I thought that boost::wave supported macro re-scanning and lookup. Is there something I'm missing, or do I need to do something with the processing hooks to make the expansion happen? I mean, I can write code to descend the tree, but it would be certainly nice if I didn't have to do that work if I was missing something important.
The clue from n.m. was important. Macros may be defined and undefined whenever, so it's only the instance of use which is relevant.
This was far easier than I had expected. If I have something that looks like this in a header file:
#define str(s) #s
#define xstr(s) str(s)
...
#define MAJORVER 1
#define MINORVER 0
#define MAJORBUILD 0
#define MINORBUILD 1
#define FULLBUILDSTRING xstr(MAJORVER) "." \
xstr(MINORVER) "." \
xstr(MAJORBUILD) "." \
xstr(MINORBUILD)
The FULLBUILDSTRING macro will evaluate to just the string as declared. However, if I have some code that makes use of the macro directly, such as in
static char const full_build_string[] = FULLBUILDSTRING;
It will evaluate to the following when Wave processes it:
static char const full_build_string = "1" "." "0" "." "0" "." "1";
If you need to see how the macros are defined after processing is complete, you can always do something like so (this is taken from the Wave driver code):
auto end = ctx.macro_names_end();
for (auto it = ctx.macro_names_begin(); it != end; ++it) {
typedef std::vector<context_type::token_type> parameters_type;
bool has_pars = false;
bool predef = false;
context_type::position_type pos;
parameters_type pars;
context_type::token_sequence_type def;
if (ctx.get_macro_definition(*it, has_pars, predef, pos, pars, def)) {
// if has_pars is true, you can iterate through pars to see
// parameters for function macros
// iterate through def to see the macro definition
}
}
Of course, the macros are stored in non-expanded form.
(n.m., if you write an answer, I will accept it)

Passing an enum string (not value) to a macro

So I had this query wherein say I have an enum and a struct that look like these,
enum fields {
field_1,
field_2
};
struct my_struct {
int field_1;
int field_2;
};
My specific need is, given the enum with the names of the structure members (field_1, field_2 etc) I should be able to generate a macro which can set the structure member to a given value.
#define my_macro (__a, __field) \
__a.__field = 1;
So is there a way to call my_macro like this:
struct my_struct b;
/* extract members of enum as string literals */
my_macro(b, /*field name from the enum */);
Few other posts detailing usage of boost macros helps me extract the enum members as strings ( How to convert an enum type variable to a string?). Issue is with passing it in the appropriate manner to the macro.
It should work the way it is. Macros are processed before compilation, while the code is still code, and they result in code generation.
Your macro #define my_macro(__a, __field) __a.__field = 1; will cause any entry like my_macro(x, y) to be transformed into x.y = 1;, literally, before its handed to the compiler.
If you do something like my_macro(1+1, "test"), it will generate the code 1+1."test" = 1; and will create a compile error. Thats how simple macros are.
Thats why macro parameters are often enclosed by () to make sure it will work the way it was intented, if you don't do that things like this can happen:
#define div_by_100(a) a / 100
printf("%d\n", div_by_100(1000)); // will print 10
printf("%d\n", div_by_100(500 + 500)); // will print 505
This happens because order of operations is resolved at compile time, after the macros have been resolved.
Notice that, because macros are resolved before compilation, they are not a runtime solution. If this enum value is not explict in the code, macros won't help you at all. You will have to write a routing function that will assign a value to each member of this class/struct depending on what enum value was given. Example:
void route(struct farm* s, enum animals e)
{
switch (e)
{
case cow:
s->cow = 1;
break;
case duck:
s->duck = 1;
break;
case horse:
s->horse = 1;
break;
case goat:
s->goat = 1;
break;
}
}
It depends on the way your mechanism of turning an enum to a string works. Your macro should work as long as that mechanism is still a macro that gets replaced by the preprocessor. That's the issue. Your macro should otherwise work properly.

C/C++: any way to get reflective enums?

I've encountered this situation so many times...
enum Fruit {
Apple,
Banana,
Pear,
Tomato
};
Now I have Fruit f; // banana and I want to go from f to the string "Banana"; or I have string s = "Banana" and from that I want to go to Banana // enum value or int.
So far I've been doing this.. Assuming the enum is in Fruit.h:
// Fruit.cpp
const char *Fruits[] = {
"Apple",
"Banana",
"Pear",
"Tomato",
NULL
};
Obviously that's a messy solution. If a developer adds a new fruit to the header and doesn't add a new entry in Fruits[] (can't blame him, they have to be in two different files!) the application goes boom.
Is there a simple way to do what I want, where everything is in one file? Preprocessor hacks, alien magic, anything..
PS: This, contrary to reflection "for everything", would be really trivial to implement in compilers. Seeing how common a problem it is (at least for me) I really can't believe there is no reflective enum Fruit.. Not even in C++0x.
PS2: I'm using C++ but I tagged this question as C as well because C has the same problem. If your solution includes C++ only things, that's ok for me.
This one requires the fruits to be defined in an external file.
This would be the content of fruit.cpp:
#define FRUIT(name) name
enum Fruit {
#include "fruit-defs.h"
NUM_FRUITS
};
#undef FRUIT
#define FRUIT(name) #name
const char *Fruits [] = {
#include "fruit-defs.h"
NULL
};
#undef FRUIT
And this would be fruit-defs.h:
FRUIT(Banana),
FRUIT(Apple),
FRUIT(Pear),
FRUIT(Tomato),
It works as long as the values start in 0 and are consecutive...
Update: mix this solution with the one from Richard Pennington using C99 if you need non-consecutive values. Ie, something like:
// This would be in fruit-defs.h
FRUIT(Banana, 7)
...
// This one for the enum
#define FRUIT(name, number) name = number
....
// This one for the char *[]
#define FRUIT(name, number) [number] = #name
A c99 way that I've found helps reduce mistakes:
enum Fruit {
APPLE,
BANANA
};
const char* Fruits[] = {
[APPLE] = "APPLE",
[BANANA] = "BANANA"
};
You can add enums, even in the middle, and not break old definitions. You can still get NULL strings for values you forget, of course.
One trick I've done in the past is to add an extra enum and then do a compile time assert (such as Boost's) to make sure the two are kept in sync:
enum Fruit {
APPLE,
BANANA,
// MUST BE LAST ENUM
LAST_FRUIT
};
const char *FruitNames[] =
{
"Apple",
"Banana",
};
BOOST_STATIC_ASSERT((sizeof(FruitNames) / sizeof(*FruitNames)) == LAST_FRUIT);
This will at least prevent someone from forgetting to add to both the enum and the name array and will let them know as soon as they try to compile.
One comment on the macro solution - you don't need a separate file for the enumerators. Just use another macro:
#define FRUITs \
FRUIT(Banana), \
FRUIT(Apple), \
FRUIT(Pear), \
FRUIT(Tomato)
(I would probably leave the commas out, though, and incorporate them into the FRUIT macro as needed.)
There is also Better Enums, which is a head-only library (file) that requires C++11 and is licensed under the BSD software license. Official description:
Reflective compile-time enums for C+: Better Enums is a single, lightweight header file that makes your compiler generate reflective enum types.
Here is the code example from the official website:
#include <enum.h>
BETTER_ENUM(Channel, int, Red = 1, Green, Blue)
Channel c = Channel::_from_string("Red");
const char *s = c._to_string();
size_t n = Channel::_size();
for (Channel c : Channel::_values()) {
run_some_function(c);
}
switch (c) {
case Channel::Red: // ...
case Channel::Green: // ...
case Channel::Blue: // ...
}
Channel c = Channel::_from_integral(3);
constexpr Channel c =
Channel::_from_string("Blue");
It looks very promising, though I haven't tested it yet. In addition there are plenty of (custom) reflection libraries for C++. I hope something similar to Better Enums will be part of the Standard Template Library (STL) (or at least Boost), sooner or later.
What if you did something like this?
enum Fruit {
Apple,
Banana,
NumFruits
};
const char *Fruits[NumFruits] = {
"Apple",
"Banana",
};
Then if you add a new entry to the Fruit enum, your compiler should complain that there are insufficient entries in the initializer of the array, so you would be forced to add an entry to the array.
So it protects you from having the array be the wrong size, but it doesn't help you ensure that the strings are correct.
Take a look at Metaresc library https://github.com/alexanderchuranov/Metaresc
It provides interface for types declaration that will also generate meta-data for the type. Based on meta-data you can easily serialize/deserialize objects of any complexity. Out of the box you can serialize/deserialize XML, JSON, XDR, Lisp-like notation, C-init notation.
Here is a simple example:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "metaresc.h"
TYPEDEF_ENUM (fruit_t,
Apple,
Banana,
Pear,
Tomato,
);
int main (int argc, char * argv[])
{
mr_td_t * tdp = mr_get_td_by_name ("fruit_t");
if (tdp)
{
int i;
for (i = 0; i < tdp->fields_size / sizeof (tdp->fields[0]); ++i)
printf ("[%" SCNd64 "] = %s\n", tdp->fields[i].fdp->param.enum_value, tdp->fields[i].fdp->name.str);
}
return (EXIT_SUCCESS);
}
This program will output
$ ./enum
[0] = Apple
[1] = Banana
[2] = Pear
[3] = Tomato
Library works fine for latest gcc and clang.
Could make a class structure for it:
class Fruit {
int value; char const * name ;
protected:
Fruit( int v, char const * n ) : value(v), name(n) {}
public:
int asInt() const { return value ; }
char const * cstr() { return name ; }
} ;
#define MAKE_FRUIT_ELEMENT( x, v ) class x : public Fruit { x() : Fruit( v, #x ) {} }
// Then somewhere:
MAKE_FRUIT_ELEMENT(Apple, 1);
MAKE_FRUIT_ELEMENT(Banana, 2);
MAKE_FRUIT_ELEMENT(Pear, 3);
Then you can have a function that takes a Fruit, and it will even be more type safe.
void foo( Fruit f ) {
std::cout << f.cstr() << std::endl;
switch (f.asInt()) { /* do whatever * } ;
}
The sizeof this is 2x bigger than just an enum. But more than likely that doesn't matter.
As the other people answering the question have shown, there isn't really a clean ("D.R.Y.") way to do this using the C preprocessor alone. The problem is that you need to define an array of size of your enum containing strings corresponding to each enum value, and the C preprocessor isn't smart enough to be able to do that. What I do is to create a text file something like this:
%status ok
%meaning
The routine completed its work successfully.
%
%status eof_reading_content
%meaning
The routine encountered the end of the input before it expected
to.
%
Here %'s mark delimiters.
Then a Perl script, the working part of which looks like this,
sub get_statuses
{
my ($base_name, $prefix) = #_;
my #statuses;
my $status_txt_file = "$base_name.txt";
my $status_text = file_slurp ($status_txt_file);
while ($status_text =~
m/
\%status\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\n
\%meaning\s*(.*?)\s*\n\%\s*\n
/gxs) {
my ($code, $meaning) = ($1, $2);
$code = $prefix."_$code";
$meaning =~ s/\s+/ /g;
push #statuses, [$code, $meaning];
}
return #statuses;
}
reads this file and writes a header file:
typedef enum kinopiko_status {
kinopiko_status_ok,
kinopiko_status_eof_reading_content,
and a C file:
/* Generated by ./kinopiko-status.pl at 2009-11-09 23:45. */
#include "kinopiko-status.h"
const char * kinopiko_status_strings[26] = {
"The routine completed its work successfully.",
"The routine encountered the end of the input before it expected to. ",
using the input file at the top. It also calculates the number 26 here by counting the input lines. (There are twenty-six possible statuses in fact.)
Then the construction of the status string file is automated using make.
I don't like macro solutions, in general, though I admit it's kind of difficult there to avoid them.
Personally I opted for a custom class to wrap my enums in. The goal was to offer a bit more that traditional enums (like iteration).
Under the cover, I use a std::map to map the enum to its std::string counterpart. Then I can use this to both iterate over the enum and "pretty print" my enum or initialize it from a string read in a file.
The problem, of course, is the definition, since I have to first declare the enum and then map it... but that's the price you pay for using them.
Also, I then use not a real enum, but a const_iterator pointing to the map (under the covers) to represent the enum value (with end representing an invalid value).

How to generate random variable names in C++ using macros?

I'm creating a macro in C++ that declares a variable and assigns some value to it. Depending on how the macro is used, the second occurrence of the macro can override the value of the first variable. For instance:
#define MY_MACRO int my_variable_[random-number-here] = getCurrentTime();
The other motivation to use that is to avoid selecting certain name to the variable so that it be the same as a name eventually chosen by the developer using the macro.
Is there a way to generate random variable names inside a macro in C++?
-- Edit --
I mean unique but also random once I can use my macro twice in a block and in this case it will generate something like:
int unique_variable_name;
...
int unique_variable_name;
In this case, to be unique both variable names have to be random generated.
Try the following:
// One level of macro indirection is required in order to resolve __COUNTER__,
// and get varname1 instead of varname__COUNTER__.
#define CONCAT(a, b) CONCAT_INNER(a, b)
#define CONCAT_INNER(a, b) a ## b
#define UNIQUE_NAME(base) CONCAT(base, __COUNTER__)
void main() {
int UNIQUE_NAME(foo) = 123; // int foo0 = 123;
std::cout << foo0; // prints "123"
}
__COUNTER__ may have portability issues. If this is a problem, you can use __LINE__ instead and as long as you aren't calling the macro more than once per line or sharing the names across compilation units, you will be just fine.
use __COUNTER__ (works on gcc4.8, clang 3.5 and Intel icc v13, MSVC 2015)
#define CONCAT_(x,y) x##y
#define CONCAT(x,y) CONCAT_(x,y)
#define uniquename static bool CONCAT(sb_, __COUNTER__) = false
Add M4 to your build flow? This macro language has some stateful capabilities, and can successfully be intermingled with CPP macros. This is probably not a standard way to generate unique names in a C environment, though I've been able to sucessfully use it in such a manner.
You probably do not not want random, BTW, based on the way you posed your question. You want unique.
You could use __FILE__ and __LINE__ in the macro expansion to get you the uniqueness you seem to be going for... those metavariables get defined within the source file context, so be careful to make sure you get what you are looking for (e.g., perils of more than one macro on the same line).
Generating unique names in the preprocessor is difficult. The closest you can get is to mangle __FILE__ and __LINE__ into the symbol as popcnt suggests. If you really need to generate unique global symbol names, then I would follow his suggestion about using something like M4 or a Perl script in your build system instead.
You might not need unique names. If your macro can impose a new scope, then you can use the same name since it will simply shadow other definitions. I usually follow the common advice of wrapping macros in do { ... } while (0) loops. This only works for macros which are statements - not expressions. The macro can update variables using output parameters. For example:
#define CALC_TIME_SINCE(t0, OUT) do { \
std::time_t _tNow = std::time(NULL); \
(OUT) = _tNow - (t0); \
} while (0)
If you follow a few rules, you are usually pretty safe:
Use leading underscores or similar naming conventions for symbols defined within the macro. This will prevent problems associated with a parameter using the same symbol from occurring.
Only use the input parameters once and always surround them with parentheses. This is the only way to make macros work with expressions as input.
Use the do { ... } while (0) idiom to ensure that the macro is only used as a statement and to avoid other textual replacement problems.
Instead of having the preprocesser create a name, you could possibly let the macro user give you a name.
#define MY_MACRO(varname) int varname = getCurrentTime();
I needed something similar for a case where I didn't have any profiling tools, but I wanted to count how many threads were inside a particular block of code as well as the amount of time (ticks) spent in that block of code by each thread, In this case every block needed a unique static variable accessible to all threads, and I needed to later reference that variable to incr (I used a logging API rather than printf in the actual code, but this works as well). At first I thought I was very clever by doing the following:
#define PROF_START { \
static volatile int entry_count##___FUNCTION__##__LINE__ = 0; int *ptc = &entry_count##___FUNCTION__##__LINE__; \
clock_t start, end; \
start = times(0); \
(*ptc)++;
But then I realized this is just silly and the C compiler will simply do this for you, as long as each "static" declaration is its own block:
#include <stdio.h>
#include <sys/times.h>
#define PROF_START { \
static int entry_count = 0; \
clock_t start, end; \
start = times(0); \
entry_count++;
#define PROF_END \
end = times(0); \
printf("[%s:%d] TIMER: %ld:%d\n" , __FUNCTION__, __LINE__, end-start, entry_count); \
entry_count--; \
}
Note the open/close brackets in each macro. This isn't strictly thread-safe, but for my profiling purposes I could assume the incr and decr operations were atomic. Here's a recursion sample which uses the macros
#define ITEM_COUNT 5
struct node {
int data;
struct node *next;
};
revsort(struct node **head)
{
struct node *current = *head;
struct node *next_item;
while (current->next)
{
PROF_START
next_item = current->next;
current->next = next_item->next;
next_item->next = *head;
*head = next_item;
PROF_END
}
}
rrevsort(struct node **head)
{
struct node *current = *head;
struct node *next_item = current->next;
PROF_START
current->next = 0;
if (next_item)
{
*head = next_item;
rrevsort(head);
next_item->next = current;
}
PROF_END
}
printnode(struct node *head)
{
if (head)
{
printf("%d ", head->data);
printnode(head->next);
}
else
printf("\n");
}
main()
{
struct node node_list[ITEM_COUNT];
struct node *head = &node_list[0];
int i;
for (i=0; i < ITEM_COUNT - 1; i++)
{
PROF_START
node_list[i].data = i;
node_list[i].next = &node_list[i+1];
PROF_END
}
node_list[i].data = i;
node_list[i].next = 0;
printf("before\n");
printnode(head);
revsort(&head);
printf("after\n");
printnode(head);
rrevsort(&head);
printf("before\n");
printnode(head);
}
Extra hint, the above program is a common interview question. Excerpt from "nm -A":
macro:0804a034 b entry_count.1715
macro:0804a030 b entry_count.1739
macro:0804a028 b entry_count.1768
macro:0804a02c b entry_count.1775
Here is a succinct macro definition to generate the singleton pattern above.
#define SINGLETON_IMPLIMENTATION(CLASS_NAME) static CLASS_NAME *g##CLASS_NAME = nil; + (CLASS_NAME *)instance { #synchronized(self) { if (g##CLASS_NAME == nil) g##CLASS_NAME = [self new]; } return g##CLASS_NAME; }
#define SINGLETON_DECLARATION(CLASS_NAME) + (CLASS_NAME *)instance;
While I don't think its even possible, you should seriously consider making a class out of this.
If you want a random element in a random array to hold a certain value, you can do this:
std::vector< std::vector<int> > m_vec;
Then wrap it in a class, so the developer can only set a number:
void set(int foo)
{
m_vec[random()][random()] = foo;
}
Is there any reason why you want it a macro? Random variable name sounds dangerous, what if it picks something already defined somewhere else in the code?