ForgottenCat's blog

By ForgottenCat, history, 92 minutes ago, In English

1.The VA_ARGS traverse define, which only takes $$$O(logN)$$$ lines.

Normally to do this, you need to:

#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.

// 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.

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 \lt tuple_size \lt decltype($$$)>::value>{});})
#define max(...)({auto $$$=make_tuple(__VA_ARGS__);t$$$(max)($$$,make_index_sequence \lt tuple_size \lt 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.

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 \lt tuple_size \lt decltype($$$)>::value>{}); \
	})
#define max(...) \
	({ \
		auto $ = make_tuple(__VA_ARGS__); \
		t$(max)($$$, make_index_sequence \lt tuple_size \lt decltype($$$)>::value>{}); \
	})

Example usages:

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.

  • Vote: I like it
  • -5
  • Vote: I do not like it

»
91 minute(s) ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by ForgottenCat (previous revision, new revision, compare).

»
70 minutes ago, hide # |
 
Vote: I like it +1 Vote: I do not like it

you can just do min({1, 2, 3})