angelbeats's blog

By angelbeats, 4 years ago, In English
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

  • Vote: I like it
  • +10
  • Vote: I do not like it

| Write comment?
»
4 years ago, # |
  Vote: I like it +8 Vote: I do not like it

What's the point?

  • »
    »
    4 years ago, # ^ |
      Vote: I like it +3 Vote: I do not like it

    Changing the code from REP(i, a) to FOR(i, 1, a) is annoying

»
4 years ago, # |
Rev. 3   Vote: I like it +13 Vote: I do not like it
»
4 years ago, # |
  Vote: I like it +27 Vote: I do not like it

Beware of side effects. rep(i, get_min(), get_max()) will call the functions several times.

»
4 years ago, # |
  Vote: I like it +49 Vote: I do not like it
Solution