#ifdef USE_BUFFER_IO
#include "optimization.h"
#else
#include <iostream>
#endif
namespace template_io {
namespace meta {
template<typename ...Ts>
struct type_list {
};
template<typename T, size_t N>
class make_n_list {
template<typename = std::make_index_sequence<N>>
struct impl;
template<size_t... Is>
struct impl<std::index_sequence<Is...>> {
template<size_t>
using wrap = T;
using type = type_list<wrap<Is>...>;
};
public:
using type = typename impl<>::type;
};
template<typename T, size_t N>
using make_n_list_t = typename make_n_list<T, N>::type;
template<typename T, typename...>
struct head {
using type = T;
};
template<typename ...Ts>
using head_t = typename head<Ts...>::type;
}
namespace input {
template<typename T, typename = void>
struct reader {
};
#ifdef USE_BUFFER_IO
template<typename T>
struct reader<T, std::enable_if_t<std::is_integral_v<T>>> {
static auto func() {
return readInt<T>();
}
};
template<>
struct reader<double> {
static auto func() {
return readDouble();
}
};
#else
template<typename T>
struct reader<T, std::enable_if_t<std::is_integral_v<T>>> {
static auto func() {
T x;
std::cin >> x;
return x;
}
};
template<>
struct reader<double> {
static auto func() {
double x;
std::cin >> x;
return x;
}
};
#endif
template<typename T>
auto read() {
return reader<T>::func();
}
template<typename ...Ts, typename = std::enable_if_t<sizeof...(Ts) >= 2>>
auto read() {
return std::tuple{read<Ts>()...};
}
template<typename ...Ts, typename = std::enable_if_t<sizeof...(Ts) >= 1>>
auto read(meta::type_list<Ts...>) {
return read<Ts...>();
}
template<size_t N, typename T = int>
auto read() {
return read(meta::make_n_list_t<T, N>());
}
struct read_s {
template<typename T>
operator T() {
return read<T>();
}
};
auto read() {
return read_s();
}
}
namespace output {
template<typename T, typename = void>
struct writer {
};
#ifdef USE_BUFFER_IO
template<typename T>
struct writer<T, std::enable_if_t<std::is_integral_v<T>>> {
static void func(const T& t, char end) {
writeInt<T>(t, end);
}
};
template<>
struct writer<double> {
static auto func(double d, char end) {
writeDouble(d);
if (end) writeChar(end);
}
};
#else
template<typename T>
struct writer<T, std::enable_if_t<std::is_integral_v<T>>> {
static void func(const T& t, char end) {
std::cout << t << end;
}
};
template<>
struct writer<double> {
static auto func(double d, char end) {
std::cout << d << end;
}
};
#endif
template<typename T>
void write(T t, char end = '\0') {
return writer<T>::func(t, end);
}
}
using input::read, output::write;
}
Comments