Replacing open bracket character in a C/C++ macro - c++

I need a macro to pass the __FILE__ and __LINE__ to a function which has default arguments. This has opened up a can of worms, since default args with macros are either not possible or very messy, and I need to support both GCC and MSVC if possible:
class Class
{
#ifdef _DEBUG
int Function(int a, int b = 10, int c = 20) { return a + b + c; }
#else
int DebugFunction(const char* filename, int lineNo, int a, int b = 10, int c = 20)
{
printf("%s (%i) a:%i b:%i c:%i\n", filename, lineNo, a, b, c);
return a + b + c;
}
//Not possible
#define Function( DebugFunction(__FILE__, __LINE__
#endif
}
I've tried \escaping the ( to no avail. The codebase is huge, so fixing up the missing default args or creating multiple macros isn't a popular option.
Any solutions?

You can make a variadic macro:
#define Function(...) DebugFunction(__FILE__, __LINE__, __VA_ARGS__)
Since you cannot "overload" macros, this might be your best bet.

One option would be to rewrite your main function Function like this:
int Function(const char* filename, int lineNo, int a, int b = 10, int c = 20)
{
#ifdef _DEBUG
printf("%s (%i) a:%i b:%i c:%i\n", filename, lineNo, a, b, c);
#endif
return a + b + c;
}
That way, all the calls go to the same function, but the behavior of that function depends on whether or not you have the _DEBUG flag set. This bypasses the issue of default arguments, since you just have a normal function call with conditional code inclusion rather than a macro that might need many arguments.
Hope this helps!

I'm not quite sure I understand what you're trying to do, but would a variadic macro do the trick?

Not a big c++ guy, but have you tried something like (in pseudocode)
#ifdef debug
#define Function(args) _Function(__file__, __line__, (args))
int _Function(char *file, int line, args) { /* code */ }
#else
#define Function(args) _Function(args)
int _Function(args) { /* code */ }
#endif
The function itself needs to be able to take multiple versions of arguments, of course; I don't really see any other way of doing this.

Related

C/C++ aliasing functions to other function with different arguments

The following is some background as to what I want to do and why. The actual question is at the very bottom...
I have an API that has some format.
For instance
int f(void *str1, void *str2) {...}
I want to reimplement the system behind the API so that it can be a drop in replacement for the old system. However it turns out that str1 is now unnecessary and moreover doesn't make sense to have if you're aware that you're using my new system. Therefore, I want to be able to expose the underlying API that makes sense:
int f_internal(void *str2);
Right now I have code that looks like this:
#ifdef USE_INTERNAL
#define INTERNAL(sym) sym##_internal
#else
#define INTERNAL(sym) sym
#endif
extern "C" {
#ifndef USE_INTERNAL
int f(void *str1, void *str2){
return INTERNAL(f)(str2);
}
#endif
SOME_ATTRIBUTES
int
INTERNAL(f)(void *str2){
... // actual content
} EXPORT_FUNCTION_MACRO(INTERNAL(f), 1);
}
The effect is if I define USE_INTERNAL, a call to f(a) works, but I don't define it then we have to use the f(a, b).
The problem I am encountering is that EXPORT_FUNCTION_MACRO itself defines another function name but doesn't evaluate INTERNAL(F) first. This results in the message
dir: error: pasting ")" and "_" does not give a valid preprocessing token
INTERNAL(sym) \
--- NOTE--- EXPORT_FUNCTION_MACRO takes args 'sys' and 'n'
other_dir: note: in definition of macro ‘EXPORT_FUNCTION_MACRO’
void _example##sym##_##n(void) {} \
WHAT I WANT TO DO:
I want to have a compile flag that can change the number of arguments needed to call something.
Maybe something like (if it existed)
using f(a, b) = f_internal(a);
Any ideas?
This results in the message
To fix the message let macro arguments expand before concatenating them.
#define EXPORT_FUNCTION_MACRO_X(sys, n) EXPORT_FUNCTION_MACRO(sys, n)
EXPORT_FUNCTION_MACRO_X(INTERNAL(f), 1);
You could achieve that with a macro in the C part:
#define f(...) CONCAT(f, NUM(__VA_ARGS__, 2, 1)) (__VA_ARGS__)
#define CONCAT(X, Y) CC(X, Y)
#define CC(X, Y) X ## Y
#define NUM(X, Y, N, ...) N
#ifdef __cplusplus
extern "C"
#endif
void f_internal(void* str);
// specifically compiled for C or C++ anyway (and most likely inlined)
// -> no need for extern "C" for these:
void f1(void* str) { f_internal(str); }
void f2(void* unused, void* str) { f_internal(str); }
The macro f would select the correct function out of f1 and f2, which again would call f_internal with the correct argument. Works for both C and C++. If you prefer, you could still just provide two overloads for C++ separately and let only the C people deal with the macros.
I doubt one could call that 'elegant'; if you want to qualify as 'ugly' – up to you. But at least it works...
The following code behaves like this:
If USE_INTERNAL is defined, defines an inline (c++) / static (c) function int f(void* str).
Otherwise, defines an inline (c++) / static (c) function int f(void* str1, void* str2).
Both functions are trampolines to the actual (int f_internal(void* str)) function.
Note that since the functions are defined in the header, inline (c++) / static (c) is required to keep them from violating the ODR rule (I am a c++ person, so I don't know any way better than static to achieve this in c. If there is, please let me know).
#ifdef __cplusplus
extern "C"
#endif
int f_internal(void* str);
#ifdef USE_INTERNAL
#ifdef __cplusplus
inline
#else
static
#endif
int f(void* str1, void* str2) {
return f_internal(str2);
}
#else
#ifdef __cplusplus
inline
#else
static
#endif
int f(void* str) {
return f_internal(str);
}
#endif

Is it possible to make macros that are default arguments expand at call site?

#include <stdio.h>
void print(int a = __LINE__){printf("hello %d\n", a);}
void main(){
print();
print();
print();
print();
}
The __LINE__ macro in this case expands to 3, so the print function is called 4 times with the same value. Is there a way to convince the compiler to expand this macro at the callsite, so that the print function would be called with 6,7,8,9 instead of 3,3,3,3 with features that exist in C++11?
My usecase:
In my application, I provide multiple functions that take a unique ID. The ID should be unique per callsite/location (so if the function is called two times throught the same statement, it should receive the same id). Currently, the user always has to manually type a LOCATION macro at the callsite, like this:
#define S1(x) #x //voodoo to concat __FILE__ and __LINE__
#define S2(x) S1(x)
#define LOCATION __FILE__ S2(__LINE__)
do_stuff1(arguments, LOCATION)
do_stuff2(arguments, LOCATION)
It would be more convenient if I could save them the typing, without creating a macro for each function like this:
#define do_stuff1(do_stuff1_imp(arguments, LOCATION))
#define do_stuff2(do_stuff2_imp(arguments, LOCATION))
Hence I thought a default argument would do the trick. Is there any way to achieve this?
You seem to be looking for std::experimental::source_location, which will be std::source_location in a future standard:
#include <experimental/source_location>
void print(std::experimental::source_location const& location
= std::experimental::source_location())
{
printf("hello %s:%d\n", location.file_name(), location.line());
}
The __LINE__ macro in this case expands to 3
Sure because your function declaration is done at line 3 and the prepreprocessor expands it from there.
Another macro instead of a function declaration would do the trick well (taken from #Ejay's comment):
#define print() printf("hello %d\n", __LINE__)
See a working example here.
You can write a macro which inserts the __FILE__ and __LINE__ into the argument list:
// Note: this doesn't work with a 0-argument function. Supporting 0-arg functions
// is much harder to do; I'd recommend just having a separate macro like as follows
#define LOCATED(fn, ...) fn(__VA_ARGS__, __FILE__, __LINE__)
#define LOCATED0(fn) fn(__FILE__, __LINE__)
void print(char const* file_name, int line)
{
printf("hello %s:%d\n", file_name, line);
}
int do_something(int value, char const* file_name, int line);
int main() {
LOCATED0(print);
LOCATED(do_something, 42);
}
With a little more work, you can make it look nicer at the call-site:
#define LOCATED(...) LOCATED_##__VA_ARGS__
void print(char const* file_name, int line)
{
printf("hello %s:%d\n", file_name, line);
}
#define LOCATED_print() ::print(__FILE__, __LINE__)
int do_something(int value, char const* file_name, int line);
#define LOCATED_do_something(value) ::do_something(value, __FILE__, __LINE__)
int main() {
LOCATED(print());
LOCATED(do_something(42));
}

c++ Macro Overloading is not working

I am trying to overload a c++ preprocessor macro depending on the number of arguments..
For example, I want to do this:
FOO(1, 2, 3) //==> expandsto FOO3(1,2,3)
FOO(1, 2) //==> expandsto FOO2(1,2)
This is what I've done:
#define GET_MACRO(_1,_2,_3,NAME,...) NAME
#define FOO(...) GET_MACRO(__VA_ARGS__, FOO3, FOO2)(__VA_ARGS__)
#define FOO2(A, B) std::cout<<"2 arguments"<<std::endl;
#define FOO3(A, B, C) std::cout<<"3 arguments"<<std::endl;
int main() {
FOO(1,2,3)
return 0;
}
In VC++, however, the exact code above gives me a compiler error:
expected a ";"
What did I do wrong..?
UPDATE:
In fact, I realized this works on Ideone >>>LINK<<<... It doesn't work on Visual Studio 12..
Why is this.. and if VS doesn't support this type of macro overloading.. what are the alternatives..?
Thanks
this is VC++ Bugs of __VA_ARGS__
try this
#define ID(x) x
#define GET_MACRO(_1,_2,_3,NAME,...) NAME
#define FOO(...) ID(GET_MACRO(__VA_ARGS__, FOO3, FOO2)(__VA_ARGS__))
Looks like it's Visual studio bug, your code is valid (I can compile it with GCC). But it's bad style anyway.
#define FOO2(A, B) std::cout<<"2 arguments"<<std::endl; // add `do {...} while (0)` construction
#define FOO3(A, B, C) std::cout<<"3 arguments"<<std::endl;
int main() {
FOO(1,2,3) // Put `;` here
return 0;
}
Code should look like this:
#define FOO2(A, B) do {std::cout<<"2 arguments"<<std::endl;} while (0)
#define FOO3(A, B, C) do {std::cout<<"3 arguments"<<std::endl;} while (0)
int main() {
FOO(1,2,3); // Looks like normal function now!
return 0;
}
What is that do {} while (0) thing, you may ask? It prevents programmers from using your macro like this: FOO2(1, 2) << "text";.

C macro defining prefixed macro with condition

I wrote a logging mechanism with several log levels.
LOG_FATAL(s)
LOG_ERROR(s)
LOG_WARN(s)
...
Now I want to be able to activate or deactivate the logging for some modules.
What I do now:
#ifdef MOUDLE_LOG_ON
MODULE_LOG_FATAL(s) LOG_FATAL(s)
MODULE_LOG_ERROR(s) LOG_ERROR(s)
MODULE_LOG_WARN(s) LOG_WARN(s)
...
#else
MODULE_LOG_FATAL(s)
MODULE_LOG_ERROR(s)
MODULE_LOG_WARN(s)
...
#endif
Is there a way to place the prefixing in a macro to use it like this:
SETUPLOGGING(MODULE)
I am wondering if using macros and inline functions could solve your issue:
void inline LOG_FATAL(const char *s)
{
printf("%s\n", s);
}
#define SETUPLOGGING(x) \
void inline x ## _LOG_FATAL(const char *s) { LOG_FATAL(s); }
SETUPLOGGING(MODULE)
int main()
{
MODULE_LOG_FATAL("hello");
}
After preprocessing, this produces:
void inline LOG_FATAL(const char *s)
{
printf("%s\n", s);
}
void inline MODULE_LOG_FATAL(const char *s) { LOG_FATAL(s); }
int main()
{
MODULE_LOG_FATAL("hello");
}
Macros can't define new macros. And when defining a macro, it isn't possible to build its name from other macro, so you can't use the common work around of including a file which defines what you want.
You could use a macro to define which include file you were going to use, but then, why not use an include file and use the macro in there?

C++ macro without spaces

I need a macro to expand to a c++ comment, is that possible?
I've got this:
#define SLASH(x,y) x y
#define OUT SLASH(/,/)
int main(int argc, char *argv[])
{
OUT << "text";
return 0;
}
And need to expand to this:
{
// << "text";
return 0;
}
I've also tried this:
#define SLASH(x) /x
#define OUT SLASH(/)
But the result is still the same:
int main(int argc, char *argv[])
{
/ / << "text";
return 0;
}
No it's not possible because in C++ comments are removed before macros are expanded.
(See 2.1 of the standard, comment removal happens in phase 3, macro expansion in phase 4.)
What about replacing it with a function object that does nothing instead?
static class NullOutput {
public:
template <typename T>
const NullOutput &operator<<(T arg) const {
return *this;
}
} NullOutputObj;
#define OUT NullOutputObj
The net result is that the object is removed from the code and replaced by inlined template expansions, that are then optimized out as they do nothing. Result is absolutely no code overhead.
As others mentioned there is no guaranteed way to define the kind of macro you are looking for. Other ways to achieve results that are similar to what you seem to be trying to achieve are wrapping your output statement in a conditional block or define a custom output stream that just discarded all output. The two approaches may even be combined so that behaviour could be switched by changing a single macro definition.
Comments are removed from the source code before the preprocessor runs. So you cannot do this.
an alternate to what you want to achieve would be this :
http://donjaffer.blogspot.in/2012/09/dprintf-debug-macro-in-c.html
#define DEBUG // comment if you do not want the debug statments to appear.
#ifdef DEBUG
#define DPRINTF(fmt, ...) \
do { printf("my_file: " fmt, ## __VA_ARGS__); } while (0)
#else
#define DPRINTF(fmt, ...) \
do { } while (0)
#endif
wherever you are trying to print the statements, instead of COUT << you can use
DPRINTF("Your text here\n");