简体   繁体   中英

macro wrapping function call with default arguments

I have a function for allocating memory, which has a default argument for alignment...

void* symalloc(int numbytes, int alignment=32)

I want to get file/line numbers passed in from the call location. So, I changed it to this...

void* _symalloc(int numbytes, int alignment, const char* file, int line);
#define symalloc(numbytes, alignment) _symalloc(numbytes, alignment, __FILE__, __LINE)

But now the problem is all the callers which were not passing in alignment are broken, and there are hundreds of these.

Is there some way to have this support either being passed alignment or not, and supply the file/line in either case?

Use a variadic macro and __VA_ARGS__ (C++11 and later, and often supported by earlier compilers too):

void symalloc_(const char* file, int line, int numbytes, int alignment=32);
#define symalloc(...) (symalloc(__FILE__, __LINE__, __VA_ARGS__))

Note the rearrangement of parameters so that the default argument is on the last one.

您还需要为其他值设置默认参数,因此某些呼叫站点没有默认值并不重要:

void* _symalloc(int numbytes, int alignment = 32, const char* file = NULL, int line = 0);

It's possible with a bit of pre-processor magic (thanks to this answer )

The real trick is to work around the fact that macros cannot be overloaded. These macros works by using the arguments themselves to shift around the name of another macro (used to choose an overload) which is selected by position.

Note that the default value "32" appears inside the SYMALLOC1 macro.

#include <iostream>

void* symalloc_impl(int numbytes, int alignment, const char* file, int line){
    std::cout << file << ':' << line << "> symalloc(" << numbytes << ", " << alignment << ")\n";
    return nullptr;
}

#define SYMALLOC1(numbytes) symalloc_impl(numbytes, 32, __FILE__, __LINE__)
#define SYMALLOC2(numbytes, alignment) symalloc_impl(numbytes, alignment, __FILE__, __LINE__)
#define SYMALLOC_DISPATCH(_1,_2,NAME,...) NAME
#define symalloc(...) SYMALLOC_DISPATCH(__VA_ARGS__,SYMALLOC2,SYMALLOC1,UNUSED)(__VA_ARGS__)

int main() {

    symalloc(16);

    symalloc(64, 8);

    return 0;
}

Example output:

main.cpp:15> symalloc(16, 32)

main.cpp:17> symalloc(64, 8)

Live example here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM