#ifdef min #undef min #endif #ifdef max #undef max #endif template constexpr const T& min(const T& a, const T& b) { return a < b ? a : b; } template constexpr const T& min(const T& a, const T& b, const Args& ...args) { return min(a, min(b, args...)); } template constexpr const T& max(const T& a, const T& b) { return a > b ? a : b; } template constexpr const T& max(const T& a, const T& b, const Args& ...args) { return max(a, max(b, args...)); } template constexpr T clamp(const T& x, const T& min_, const T& max_) { return min(max(x, min_), max_); } template constexpr int findarg(const T& x, const K& k) { return x == k ? 0 : -1; } template constexpr int findarg(const T& sel, const K& k, const L& ...args) { if(sel == k) return 0; int q = findarg(sel, args...); return q >= 0 ? q + 1 : -1; } template constexpr const char *decode_chr_(const T& sel, const char *def) { return def; } template constexpr const char *decode_chr_(const T& sel, const K& k, const char *v, const L& ...args) { return sel == k ? v : decode_chr_(sel, args...); } template constexpr const char *decode(const T& sel, const K& k, const char *v, const L& ...args) { return decode_chr_(sel, k, v, args...); } template constexpr const V& decode(const T& sel, const V& def) { return def; } template constexpr V decode(const T& sel, const K& k, const V& v, const L& ...args) { return sel == k ? v : (V)decode(sel, args...); } template constexpr A get_i(int i, const A& p0, const T& ...args) { A list[] = { p0, (A)args... }; return list[clamp(i, 0, (int)sizeof...(args))]; } template constexpr const P *get_i(int i, const P* p0, const T& ...args) { const P *list[] = { p0, args... }; return list[clamp(i, 0, (int)sizeof...(args))]; } template void foreach_arg(F fn, V&& v) { fn(std::forward(v)); } template void foreach_arg(F fn, V&& v, Args&& ...args) { fn(std::forward(v)); foreach_arg(fn, std::forward(args)...); } template void iter_set(I t, Args&& ...args) { foreach_arg([&](auto&& v) { *t++ = std::forward(v); }, std::forward(args)...); } template void iter_get(I s, Args& ...args) { foreach_arg([&](auto& v) { v = *s++; }, args...); } template C gather(Args&& ...args) { C x(sizeof...(args)); iter_set(x.begin(), std::forward(args)...); return x; } template int scatter_n(int n, const C& c, Args& ...args) { if(n < (int)sizeof...(args)) return 0; iter_get(c.begin(), args...); return sizeof...(args); } template int scatter(const C& c, Args& ...args) { return scatter_n(c.size(), c, args...); } // DEPRECATED template // deprecated name, use clamp inline T minmax(T x, T _min, T _max) { return min(max(x, _min), _max); }