9

I have many variables that are named the same as elements in an engineering specification document so the string version of the name is also useful.

I find myself using a macro like this a lot:

#define MACRO(a) a, #a

Typical usage is:

void someFunction(int a, const char *name);

someFunction(MACRO(meaningfully_named_variable));

My question is threefold:

  • Is there a better way of doing this?
  • Is a similar macro available in Boost or other libraries?
  • If not, how could I refine and rename this to make it clear and useful?

Edit I should have said that the above is a minimal example. The function might have other parameters and the named entity might be a data member or perhaps even a function itself.

Another extension I'm considering for C++ is a class NamedRef that could receive the contents of the macro.

template <typename T>
struct NamedRef
{
    NamedRef(T *t, const char *name) : t(t), name(name) { }
    T *t;
    const char *name;
};

template <typename T>
NamedRef<T> namedRef(T &t, const char *name)
{
    return NamedRef<T>(&t, name);
}

#define WITH_NAME(a) a, #a

// more sophisticated usage example
void otherFunction(double, NamedRef<int>, bool);

otherFunction(0.0, namedRef(object.WITH_NAME(meaningful_member_name)), false);
2
  • 3
    All I'd do is pick a more descriptive name for the macro, e.g. WITH_NAME(). Commented Dec 21, 2011 at 23:31
  • Do what @MarkRansom suggested. My answer was a long way of saying "it's fine" and that Boost has a macro called BOOST_STRINGIZE(X).
    – AusCBloke
    Commented Dec 22, 2011 at 0:00

4 Answers 4

5

You could take it a step further:

#define SOMEFUNCTION(a) somefunction(a, #a)

However, this is only useful if you call the same function alot. Otherwise, I don't think there is any better way than your example. Of course, you should change the name of the macro to something more meaningful though, like ARGUMENTS or something.

3
  • True, but if I have a lot of functions that receive var, name then I will have to write a lot of macros.
    – paperjam
    Commented Dec 22, 2011 at 8:37
  • Not necessarily => #define MACRO(funct_ptr, var) funct_ptr(var, #var) So you will need such many macro's how many different signature of function parameters you have... Commented Dec 22, 2011 at 9:09
  • OK, good thinking, but I think it's clearer to preserve the function syntax if possible, also function may have other args.
    – paperjam
    Commented Dec 22, 2011 at 14:43
0

You are likely to find that XMACROs are useful for this kind of work.

0
#define someFunction(a)  if (1) stringized_someFunction((a), #a ); else (void)0
void stringized_someFunction(int a, const char* name);

The if (1) stuff wraps up the macro so that it won't mess (usually) with loops, branches, if statements, etc.

You would then call your function like so:

int r = 4;
someFunction(r);

You only really add one extra line for each "function declaration." If the C preprocessor allowed multiple steps you could wrap it all up into one, but alas, it doesn't.

I forgot because I hope it's obvious that you'd need to write your function:

void stringized_someFunction(int a, const char* name)
{
  // Do stuff here
}

Anyhow it should be a lot easier and prettier to read that way.

4
  • 1
    You forgot the semicolon in your macro definition before else. Also, I don`t think wrapping it in if(1) is necessary in this situation.
    – Jesse Good
    Commented Dec 22, 2011 at 0:43
  • 1
    I know that you need to wrap multi-statement macros to prevent them from breaking code, but I don't understand the reason for single statements, if you could provide a counter-example it would be appreciated.
    – Jesse Good
    Commented Dec 22, 2011 at 4:12
  • 1
    if (1) will cause problems if wrapped function needs to return a value.
    – paperjam
    Commented Dec 22, 2011 at 8:36
  • It doesn't make sense to wrap a function call within an if(1) or do{}while(0); because you can't capture the result of the function call.
    – dreamlax
    Commented Dec 22, 2011 at 9:26
0

As Jesse answered,

you can write like this:

void function1(int a, const char* name)
{
    cout << "a: " << a << endl;
    cout << "name: " << name << endl;
}

void function2(double d, const char* name, const char *str)
{
    cout << "d: " << d << endl;
    cout << "name: " << name << endl;
    cout << "str: " << str << endl;
}

#define MACRO(functionName, a) functionName(a, #a)
#define MACRO2(functionName, a, ...) functionName(a, #a, __VA_ARGS__)

int main()
{
    int a = 10;
    MACRO(function1, a);
    double d = 10.5;
    MACRO2(function2, d, "Hello world");
    return 0;
}

If you have more arguments to pass, you can use MACRO2 that uses variable arguments. You will have to pass the function name accordingly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.