overload.hpp
1
4#pragma once
5
7
8// Implementing Macro Overloding:
9// by count of given arguments, let compiler determine which macro should works.
10// original source code from BuvinJ at
11// https://stackoverflow.com/questions/11761703/overloading-macro-on-number-of-arguments
12//
13// usage:
14// // define macro:
15// #define MyMacro_0() 100
16// #define MyMacro_1(x) (x)+5
17// #define MyMacro_2(x, y) (x)+(y)
18// #define MyMacro(...) BY_OVERLOAD(MyMacro, __VA_ARGS__)
19//
20// // using:
21// cout << MyMacro(5) << ", " << MyMacro(3, 5) << ", " << MyMacro() << "\n";
22//
23// output:
24// 10, 8, 100
25#define BY_OVERLOAD(NAME, ...) BY_CONCAT(NAME##_, __OVERLOAD_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
26
27#define _ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
28#define __OVERLOAD_HAS_COMMA(...) _ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
29#define __OVERLOAD_HAS_NO_COMMA(...) _ARG16(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
30#define _TRIGGER_PARENTHESIS_(...) ,
31
32#define __OVERLOAD_HAS_ZERO_OR_ONE_ARG(...) \
33 ___OVERLOAD_HAS_ZERO_OR_ONE_ARG( /* test if there is just one argument, eventually an empty one \
34 */ \
35 __OVERLOAD_HAS_COMMA(__VA_ARGS__), /* test if _TRIGGER_PARENTHESIS_ together with the \
36 argument adds a comma */ \
37 __OVERLOAD_HAS_COMMA( \
38 _TRIGGER_PARENTHESIS_ __VA_ARGS__), /* test if the argument together with a parenthesis adds a comma */ \
39 __OVERLOAD_HAS_COMMA(__VA_ARGS__(~)), /* test if placing it between _TRIGGER_PARENTHESIS_ \
40 and the parenthesis adds a comma */ \
41 __OVERLOAD_HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__(~)))
42
43#define __OVERLOAD_PASTE5(_0, _1, _2, _3, _4) _0##_1##_2##_3##_4
44#define ___OVERLOAD_HAS_ZERO_OR_ONE_ARG(_0, _1, _2, _3) \
45 __OVERLOAD_HAS_NO_COMMA(__OVERLOAD_PASTE5(_IS_EMPTY_CASE_, _0, _1, _2, _3))
46#define _IS_EMPTY_CASE_0001 ,
47
48#define _VA0(...) __OVERLOAD_HAS_ZERO_OR_ONE_ARG(__VA_ARGS__)
49#define _VA1(...) __OVERLOAD_HAS_ZERO_OR_ONE_ARG(__VA_ARGS__)
50#define _VA2(...) 2
51#define _VA3(...) 3
52#define _VA4(...) 4
53#define _VA5(...) 5
54#define _VA6(...) 6
55#define _VA7(...) 7
56#define _VA8(...) 8
57#define _VA9(...) 9
58#define _VA10(...) 10
59#define _VA11(...) 11
60#define _VA12(...) 12
61#define _VA13(...) 13
62#define _VA14(...) 14
63#define _VA15(...) 15
64#define _VA16(...) 16
65
66#define __OVERLOAD_VA_NUM_ARGS(...) __OVERLOAD_VA_NUM_ARGS_IMPL(__VA_ARGS__, __OVERLOAD_RSEQ_N(__VA_ARGS__))
67#define __OVERLOAD_VA_NUM_ARGS_IMPL(...) __OVERLOAD_VA_NUM_ARGS_N(__VA_ARGS__)
68
69#define __OVERLOAD_VA_NUM_ARGS_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N
70
71#define __OVERLOAD_RSEQ_N(...) \
72 _VA16(__VA_ARGS__), _VA15(__VA_ARGS__), _VA14(__VA_ARGS__), _VA13(__VA_ARGS__), _VA12(__VA_ARGS__), \
73 _VA11(__VA_ARGS__), _VA10(__VA_ARGS__), _VA9(__VA_ARGS__), _VA8(__VA_ARGS__), _VA7(__VA_ARGS__), \
74 _VA6(__VA_ARGS__), _VA5(__VA_ARGS__), _VA4(__VA_ARGS__), _VA3(__VA_ARGS__), _VA2(__VA_ARGS__), \
75 _VA1(__VA_ARGS__), _VA0(__VA_ARGS__)