// SPDX-License-Identifier: GPL-2.0-or-later /* * Author: Abby Cin * Mail: abbytsing@gmail.com * Create Time: 2020-10-04 10:11:14 */ using size_t = unsigned long; struct cout { static int itoa(char buf[], int val) { static const char* const digits = "9876543210123456789"; static const char* zero = digits + 9; int i = val; char *p = buf; char *b = buf; char c; int r = 0; int lsd; do { lsd = i % 10; i /= 10; *p++ = zero[lsd]; } while (i != 0); if (val < 0) *p++ = '-'; *p = '\0'; r = p - buf; while (b < p) { --p; c = *b; *b = *p; *p = c; b++; } return r; } static void write(const char *a, size_t n) { asm volatile( "movq $1, %%rax;" "movq $1, %%rdi;" "movq %[a], %%rsi;" "movq %[n], %%rdx;" "syscall;" : : [a] "m" (a), [n] "m" (n) : ); } template cout &operator<< (const char (&a)[N]) { write(a, N); return *this; } cout &operator<< (const char *a) { int n = 0; const char *p = a; while (*p) p++; n = p - a; write(a, n); return *this; } cout &operator<< (const char a) { write(&a, 1); return *this; } cout &operator<< (int x) { static char buf[32]; int n = itoa(buf, x); write(buf, n); return *this; } }; struct cout out; template struct remove_ref { using type = T; }; template struct remove_ref { using type = T; }; template struct remove_ref { using type = T; }; template using remove_ref_t = typename remove_ref::type; template constexpr T&& forward(remove_ref_t& x) { return static_cast(x); } template constexpr T&& forward(remove_ref_t&& x) { return static_cast(x); } template struct sequence{}; template struct concat; template struct concat, sequence> { using type = sequence; }; template struct gen_seq; template<> struct gen_seq<1> { using type = sequence<0>; }; // zero based index template struct gen_seq { using type = typename concat::type, typename gen_seq::type>::type; }; template using make_sequence = typename gen_seq::type; template struct tuple_val { T value; }; template struct tuple; template<> struct tuple<> {}; template constexpr bool false_t = false; template struct tuple : tuple { using base = tuple; tuple(T&& t, Ts&&... ts) : base{::forward(ts)...}, value{::forward(t)} {} // adl is evil tuple_val value; constexpr static size_t size = sizeof...(Ts) + 1; }; template tuple(T&&, Ts&&...) -> tuple; template struct element; template struct element> { static_assert(false_t, "out of range"); }; template struct element<0, tuple> { using type = T; using base = tuple; }; template struct element> : element> {}; template using element_t = typename element::type; template constexpr element_t>& get(tuple& x) { using base = typename element>::base; return static_cast(x).value.value; } template cout& operator<< (cout& os, tuple& x) { return [&os, &x](sequence) -> cout& { ((os << get(x) << ' '), ...); return os << '\n'; }(make_sequence{}); } template R apply(F&& f, Tuple&& args) { return [f = ::forward(f), &args](sequence) { return f(::forward>>(get(args))...); }(make_sequence::size>{}); } void foo(const char *a, int b, const char *c) { out << a << ' ' << b << ' ' << c << '\n'; } int main() { tuple t{"elder", 1925, "+1s"}; get<1>(t) += 1; out << t; apply(foo, t); } asm ( ".globl _start;" "_start:" "call main;" "movq $60, %rax;" "movq $0, %rdi;" "syscall" );