Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CPP: avoiding macro expansion of a macro function parameter

what I'd like to do (for logging purposes) is something like this:

This code has been written to show my problem, actual code is complex and yes, I have good reasons to use macros even on C++ =)

# define LIB_SOME 1
# define LIB_OTHER 2

# define WHERE "at file #a, line #l, function #f: "
// (look for syntax hightlighting error at SO xd)
# define LOG_ERROR_SIMPLE(ptr, lib, str) ptr->log ("ERROR " str \
                                                   " at library " #lib);
# define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE str)

LOG_ERROR_SIMPLE (this, LIB_SOME, "doing something")
LOG_ERROR (this, LIB_OTHER, "doing something else")

LOG_ERROR_SIMPLE() writes the stringification of the lib parameter (a macro name surrounded by " ")

but then LOG_ERROR writes the stringification of the macro already expanded ("2"). this is expected, since lib got its expansion before expanding and calling LOG_ERROR_SIMPLE. but this is not what I need.

Basically my question is this: how to avoid macro expansion of a macro function parameter when calling another macro function?

There is a trick I use that avoids macro expansion:

  LOG_ERROR(ptr, lib, str, x) LOG_ERROR_SIMPLE(ptr, x##lib, WHERE str)

  LOG_ERROR(this, LIB_OTHER, "some error",)

(pasting x and lib produces LIB_OTHER and this value is used to call LOG_ERROR_SIMPLE, its not macro expanded before that call)

There is some way to obtain this same behaviour without using a trick?

like image 896
conejoroy Avatar asked Dec 10 '09 13:12

conejoroy


1 Answers

I'm doing:

#include <cstdio>

#define FOO 1
#define BAR 2

#define LOG_SIMPLE(ptr, lib, str) printf("%s\n", #lib);
#define LOG(ptr, lib, str) LOG_SIMPLE(ptr, ##lib, str)

int main()
{
  LOG_SIMPLE(0, FOO, "some error");
  LOG(0, BAR, "some other error");
}

which prints out:

FOO
BAR

Works with MSVC2005 but not with gcc/g++.


EDIT: to make it work with gcc/g++ you can abuse variadic macros:

#include <stdio.h>

#define FOO 1
#define BAR 2

#define LOG_SIMPLE(ptr, str, lib) printf("%s\n", #lib);
#define LOG(ptr, str, lib, ...) LOG_SIMPLE(ptr, str, lib##__VA_ARGS__)

int main()
{
  LOG_SIMPLE(0, "some error", FOO);
  LOG(0, "some other error", BAR);
  LOG(0, "some other error", FOO, BAR);
}

However, it's your discipline not to use the macro with too many parameters. MSVC2005 prints out

FOO
BAR
FOO2

while gcc prints out

FOO
BAR
FOOBAR
like image 124
Gregory Pakosz Avatar answered Oct 23 '22 23:10

Gregory Pakosz