portable version
#include <tuple>
using namespace std;
#define numargs(args...) tuple_size<decltype(make_tuple(args))>::value
#define argi(i, args...) get<i>(make_tuple(args))
#define rep(i, args...) for (int i = ((numargs(args) > 1) ? argi(0, args) : 0); i < argi(numargs(args) - 1, args); ++i)
#define repi(args...) rep(i, args)
First, let argv := make_tuple(args)
, to get argc
out of args
, we use argc := tuple_size<decltype(argv)>::value
, according to link. Second, we use (argc - 1 > 0) ? get<1>(argv) : 0
as the base, and get<(argc - 1)>(argv)
as the end.
The code below is tested among G++11, G++14, G++17, Clang++17. For all users including MSVC, use ...
instead of args...
and __VA_ARGS__
instead of args
.
#include <tuple>
#include <cassert>
using namespace std;
#define numargs(args...) tuple_size<decltype(make_tuple(args))>::value
#define argi(i, args...) get<i>(make_tuple(args))
#define rep(i, args...) for (int i = ((numargs(args) > 1) ? argi(0, args) : 0); i < argi(numargs(args) - 1, args); ++i)
#define repi(args...) rep(i, args)
int main() {
int s = 0;
repi(5) s += i;
rep(i, -4, 5) s += i;
assert(s == 10);
return 0;
}
By the way, I'm using #define pb(args...) push_back(args)
instead of #define pb push_back
What's the point?
Changing the code from REP(i, a) to FOR(i, 1, a) is annoying
one loop for everything
Choosing macro based on argc is really clever. It's time to get rid of old templates.
copied from tmwilliamlin168 template :)
Beware of side effects.
rep(i, get_min(), get_max())
will call the functions several times.Use no macros
for(int i = 0; i < n; i++)
for(int i = a; i < b; i++)