-
-
Save mbolt35/4e60da5aaec94dcd39ca to your computer and use it in GitHub Desktop.
Example to demonstrate using a C99 preprocessor macro to execute a variadict function without having to explicitly pass the argument list size.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// arg_helper.h | |
#ifndef ARG_HELPER_H | |
#define ARG_HELPER_H | |
#include <stdarg.h> | |
/** | |
* Using MSVC? | |
*/ | |
#define IS_MSVC _MSC_VER && !__INTEL_COMPILER | |
/** | |
* Define the macros to determine variadic argument lengths up to 20 arguments. The MSVC | |
* preprocessor handles variadic arguments a bit differently than the GNU preprocessor, | |
* so we account for that here. | |
*/ | |
#if IS_MSVC | |
#define MSVC_HACK(FUNC, ARGS) FUNC ARGS | |
#define APPLY(FUNC, ...) MSVC_HACK(FUNC, (__VA_ARGS__)) | |
#define VA_LENGTH(...) APPLY(VA_LENGTH_, 0, ## __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) | |
#else | |
#define VA_LENGTH(...) VA_LENGTH_(0, ## __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) | |
#endif | |
/** | |
* Strip the processed arguments to a length variable. | |
*/ | |
#define VA_LENGTH_(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N | |
#endif // ARG_HELPER_H | |
// ---- | |
// mymath.h | |
#ifndef MY_MATH_H | |
#define MY_MATH_H | |
#include "arg_helper.h" | |
/** | |
* Use the VA_LENGTH macro to determine the length of the variadict args to | |
* pass in as the first parameter, and forward along the arguments after that. | |
*/ | |
#define ExecVF(Func, ...) Func(VA_LENGTH(__VA_ARGS__), __VA_ARGS__) | |
namespace my { | |
namespace math { | |
template<class T> | |
extern T Min(int count, T value, ...) { | |
va_list args; | |
va_start(args, value); | |
T min = value; | |
for (int i = 0; i < count-1; ++i) { | |
T next = va_arg(args, T); | |
min = min < next ? min : next; | |
} | |
va_end(args); | |
return min; | |
} | |
}; | |
}; | |
#endif // MY_MATH_H | |
// ---- | |
// main.cpp | |
#include <cstdio> | |
#include "mymath.h" | |
int main() { | |
int min = ExecVF(my::math::Min<int>, 5, 2, 20, -3, 66, 0, 34); | |
printf("min: %d\n", min); | |
return 0; | |
} | |
// Output | |
// min: -3 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment