### 1.The __VA_ARGS__ traverse define, which only takes $O(logN)$ lines.↵
↵
Normally to do this, you need to:↵
↵
```cpp↵
#define SP1(A) ...↵
#define SP2(A,B) ...↵
#define SP3(A,B,C) ...↵
...↵
```↵
↵
Which is $O(N)$ defines. Here's an example supporting 31 or 32 (I forget) args using only $log32+5$ defines. Another 2 used for declaring a tool.↵
↵
```cpp↵
// O(logN) lines of __VA_ARGS__ traverse↵
#define SIZEOF_ARGS_H(...)SSIZEOF_ARGS_H(__VA_ARGS__,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,4,4,4,4,2,2,1)↵
#define SSIZEOF_ARGS_H($2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,N,...)N↵
#define CONCAT(a,b) CCONCAT(a,b)↵
#define CCONCAT(a,b) a##b↵
#define SP(A,B,...)CONCAT(SP,SIZEOF_ARGS_H(__VA_ARGS__))(A,B,__VA_ARGS__)↵
#define SP1(A,B,C)A(B,C)↵
#define SP2(A,B,C,D,...)A(B,C)A(B,D)__VA_OPT__(A(B,__VA_ARGS__))↵
#define SP4(A,B,C1,C2,C3,C4,...)SP2(A,B,C1,C2)SP2(A,B,C3,C4)__VA_OPT__(CONCAT(SP,SIZEOF_ARGS_H(__VA_ARGS__))(A,B,__VA_ARGS__))↵
#define SP8(A,B,C1,C2,C3,C4,C5,C6,C7,C8,...)SP4(A,B,C1,C2,C3,C4)SP4(A,B,C5,C6,C7,C8)__VA_OPT__(CONCAT(SP,SIZEOF_ARGS_H(__VA_ARGS__))(A,B,__VA_ARGS__))↵
#define SP16(A,B,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,...)SP8(A,B,C1,C2,C3,C4,C5,C6,C7,C8)SP8(A,B,C9,C10,C11,C12,C13,C14,C15,C16)__VA_OPT__(CONCAT(SP,SIZEOF_ARGS_H(__VA_ARGS__))(A,B,__VA_ARGS__))↵
// Classic usage of SP, to generate refs for struct members.↵
#define REFER(A,B)auto&B=A.B;↵
#define refer(A,...)SP(REFER,A,__VA_ARGS__)↵
// up to 31 or 32 Args available.↵
↵
struct s{int a,b,c,d,e,f;}g;↵
↵
int main(){↵
refer(g,a,b,c,d,e,f);↵
// expand to auto&a=g.a;auto&b=g.b;auto&c=g.c;......↵
a=0,b=0,c=0,d=0,e=0,f=0;↵
}↵
```↵
↵
### 2. Auto min max↵
↵
You need at least C++14 to use this.↵
↵
The min max that can automatically infer the type of return value using `common_type`.↵
↵
```cpp↵
template<class a,size_t I=0,typename=void>struct d${using type=common_type_t<decltype(get<I>(declval<a>())),typename d$<a,I+1>::type>;};template<class a,size_t I>struct d$<a,I,enable_if_t<I==tuple_size<decay_t<a>>::value-1>>{using type=decltype(get<I>(declval<a>()));};↵
#define t$(A)[&]<size_t... I>(auto &u,index_sequence<I...>){typename d$<decltype(u)>::type ma=get<0>(u);((ma=A<decltype(ma)>(ma,get<I>(u))),...);return ma;}↵
#define min(...)({auto $=make_tuple(__VA_ARGS__);t$(min)($,make_index_sequence<tuple_size<decltype($)>::value>{});})↵
#define max(...)({auto $=make_tuple(__VA_ARGS__);t$(max)($,make_index_sequence<tuple_size<decltype($)>::value>{});})↵
```↵
↵
The downside is it will call `min(A, A)` for once. For example `min(1,2,3)` will be `min(min(min(1,1),2),3)`. Maybe it can be solved cleaner by using `SP()`.↵
↵
Note that common_type_t<A, A> == A. You can even put strings there as long as they're comparable.↵
↵
Supports infinite args. After formatting it would look like this.↵
↵
```cpp↵
template<class a, size_t I = 0, typename = void>↵
struct d$↵
{↵
using type = common_type_t<decltype(get<I>(declval<a>())), typename d$<a, I + 1>::type>;↵
};↵
template<class a, size_t I>↵
struct d$<a, I, enable_if_t<I == tuple_size<decay_t<a>>::value - 1>>↵
{↵
using type = decltype(get<I>(declval<a>()));↵
};↵
#define t$(A) \↵
[&]<size_t... I>(auto &u, index_sequence<I...>) { \↵
typename d$<decltype(u)>::type ma = get<0>(u); \↵
((ma = A<decltype(ma)>(ma, get<I>(u))), ...); \↵
return ma; \↵
}↵
#define min(...) \↵
({ \↵
auto $ = make_tuple(__VA_ARGS__); \↵
t$(min)($, make_index_sequence<tuple_size<decltype($)>::value>{}); \↵
})↵
#define max(...) \↵
({ \↵
auto $ = make_tuple(__VA_ARGS__); \↵
t$(max)($, make_index_sequence<tuple_size<decltype($)>::value>{}); \↵
})↵
```↵
↵
Example usages:↵
↵
```cpp↵
auto a=min(1,2ll,3.0f);↵
// decltype(a) == float, a=1.0f↵
↵
auto b=min(string("1"),string("3"));↵
// b==string("1");↵
```↵
↵
By the way I think there's space left for optimizing, I'm not a professional STL user, cannot figure out how tf does `index_sequence` come to work. I have been using these at least two months, so there's little chance that they have secret bugs.
↵
Normally to do this, you need to:↵
↵
```cpp↵
#define SP1(A) ...↵
#define SP2(A,B) ...↵
#define SP3(A,B,C) ...↵
...↵
```↵
↵
Which is $O(N)$ defines. Here's an example supporting 31 or 32 (I forget) args using only $log32+5$ defines. Another 2 used for declaring a tool.↵
↵
```cpp↵
// O(logN) lines of __VA_ARGS__ traverse↵
#define SIZEOF_ARGS_H(...)SSIZEOF_ARGS_H(__VA_ARGS__,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,4,4,4,4,2,2,1)↵
#define SSIZEOF_ARGS_H($2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,N,...)N↵
#define CONCAT(a,b) CCONCAT(a,b)↵
#define CCONCAT(a,b) a##b↵
#define SP(A,B,...)CONCAT(SP,SIZEOF_ARGS_H(__VA_ARGS__))(A,B,__VA_ARGS__)↵
#define SP1(A,B,C)A(B,C)↵
#define SP2(A,B,C,D,...)A(B,C)A(B,D)__VA_OPT__(A(B,__VA_ARGS__))↵
#define SP4(A,B,C1,C2,C3,C4,...)SP2(A,B,C1,C2)SP2(A,B,C3,C4)__VA_OPT__(CONCAT(SP,SIZEOF_ARGS_H(__VA_ARGS__))(A,B,__VA_ARGS__))↵
#define SP8(A,B,C1,C2,C3,C4,C5,C6,C7,C8,...)SP4(A,B,C1,C2,C3,C4)SP4(A,B,C5,C6,C7,C8)__VA_OPT__(CONCAT(SP,SIZEOF_ARGS_H(__VA_ARGS__))(A,B,__VA_ARGS__))↵
#define SP16(A,B,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,...)SP8(A,B,C1,C2,C3,C4,C5,C6,C7,C8)SP8(A,B,C9,C10,C11,C12,C13,C14,C15,C16)__VA_OPT__(CONCAT(SP,SIZEOF_ARGS_H(__VA_ARGS__))(A,B,__VA_ARGS__))↵
// Classic usage of SP, to generate refs for struct members.↵
#define REFER(A,B)auto&B=A.B;↵
#define refer(A,...)SP(REFER,A,__VA_ARGS__)↵
// up to 31 or 32 Args available.↵
↵
struct s{int a,b,c,d,e,f;}g;↵
↵
int main(){↵
refer(g,a,b,c,d,e,f);↵
// expand to auto&a=g.a;auto&b=g.b;auto&c=g.c;......↵
a=0,b=0,c=0,d=0,e=0,f=0;↵
}↵
```↵
↵
### 2. Auto min max↵
↵
You need at least C++14 to use this.↵
↵
The min max that can automatically infer the type of return value using `common_type`.↵
↵
```cpp↵
template<class a,size_t I=0,typename=void>struct d${using type=common_type_t<decltype(get<I>(declval<a>())),typename d$<a,I+1>::type>;};template<class a,size_t I>struct d$<a,I,enable_if_t<I==tuple_size<decay_t<a>>::value-1>>{using type=decltype(get<I>(declval<a>()));};↵
#define t$(A)[&]<size_t... I>(auto &u,index_sequence<I...>){typename d$<decltype(u)>::type ma=get<0>(u);((ma=A<decltype(ma)>(ma,get<I>(u))),...);return ma;}↵
#define min(...)({auto $=make_tuple(__VA_ARGS__);t$(min)($,make_index_sequence<tuple_size<decltype($)>::value>{});})↵
#define max(...)({auto $=make_tuple(__VA_ARGS__);t$(max)($,make_index_sequence<tuple_size<decltype($)>::value>{});})↵
```↵
↵
The downside is it will call `min(A, A)` for once. For example `min(1,2,3)` will be `min(min(min(1,1),2),3)`. Maybe it can be solved cleaner by using `SP()`.↵
↵
Note that common_type_t<A, A> == A. You can even put strings there as long as they're comparable.↵
↵
Supports infinite args. After formatting it would look like this.↵
↵
```cpp↵
template<class a, size_t I = 0, typename = void>↵
struct d$↵
{↵
using type = common_type_t<decltype(get<I>(declval<a>())), typename d$<a, I + 1>::type>;↵
};↵
template<class a, size_t I>↵
struct d$<a, I, enable_if_t<I == tuple_size<decay_t<a>>::value - 1>>↵
{↵
using type = decltype(get<I>(declval<a>()));↵
};↵
#define t$(A) \↵
[&]<size_t... I>(auto &u, index_sequence<I...>) { \↵
typename d$<decltype(u)>::type ma = get<0>(u); \↵
((ma = A<decltype(ma)>(ma, get<I>(u))), ...); \↵
return ma; \↵
}↵
#define min(...) \↵
({ \↵
auto $ = make_tuple(__VA_ARGS__); \↵
t$(min)($, make_index_sequence<tuple_size<decltype($)>::value>{}); \↵
})↵
#define max(...) \↵
({ \↵
auto $ = make_tuple(__VA_ARGS__); \↵
t$(max)($, make_index_sequence<tuple_size<decltype($)>::value>{}); \↵
})↵
```↵
↵
Example usages:↵
↵
```cpp↵
auto a=min(1,2ll,3.0f);↵
// decltype(a) == float, a=1.0f↵
↵
auto b=min(string("1"),string("3"));↵
// b==string("1");↵
```↵
↵
By the way I think there's space left for optimizing, I'm not a professional STL user, cannot figure out how tf does `index_sequence` come to work. I have been using these at least two months, so there's little chance that they have secret bugs.



