#include using namespace std; #include using namespace atcoder; #include #include #include #ifndef DBG_MACRO_DBG_H #define DBG_MACRO_DBG_H #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #define DBG_MACRO_UNIX #elif defined(_MSC_VER) #define DBG_MACRO_WINDOWS #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DBG_MACRO_UNIX #include #endif #if __cplusplus >= 201703L #define DBG_MACRO_CXX_STANDARD 17 #elif __cplusplus >= 201402L #define DBG_MACRO_CXX_STANDARD 14 #else #define DBG_MACRO_CXX_STANDARD 11 #endif #if DBG_MACRO_CXX_STANDARD >= 17 #include #include #endif namespace dbg { #ifdef DBG_MACRO_UNIX inline bool isColorizedOutputEnabled() { return isatty(fileno(stderr)); } #else inline bool isColorizedOutputEnabled() { return true; } #endif struct time {}; namespace pretty_function { // Compiler-agnostic version of __PRETTY_FUNCTION__ and constants to // extract the template argument in `type_name_impl` #if defined(__clang__) #define DBG_MACRO_PRETTY_FUNCTION __PRETTY_FUNCTION__ static constexpr size_t PREFIX_LENGTH = sizeof("const char *dbg::type_name_impl() [T = ") - 1; static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1; #elif defined(__GNUC__) && !defined(__clang__) #define DBG_MACRO_PRETTY_FUNCTION __PRETTY_FUNCTION__ static constexpr size_t PREFIX_LENGTH = sizeof("const char* dbg::type_name_impl() [with T = ") - 1; static constexpr size_t SUFFIX_LENGTH = sizeof("]") - 1; #elif defined(_MSC_VER) #define DBG_MACRO_PRETTY_FUNCTION __FUNCSIG__ static constexpr size_t PREFIX_LENGTH = sizeof("const char *__cdecl dbg::type_name_impl<") - 1; static constexpr size_t SUFFIX_LENGTH = sizeof(">(void)") - 1; #else #error "This compiler is currently not supported by dbg_macro." #endif } // namespace pretty_function // Formatting helpers template struct print_formatted { static_assert(std::is_integral::value, "Only integral types are supported."); print_formatted(T value, int numeric_base) : inner(value), base(numeric_base) {} operator T() const { return inner; } const char* prefix() const { switch (base) { case 8: return "0o"; case 16: return "0x"; case 2: return "0b"; default: return ""; } } T inner; int base; }; template print_formatted hex(T value) { return print_formatted{value, 16}; } template print_formatted oct(T value) { return print_formatted{value, 8}; } template print_formatted bin(T value) { return print_formatted{value, 2}; } // Implementation of 'type_name()' template const char* type_name_impl() { return DBG_MACRO_PRETTY_FUNCTION; } template struct type_tag {}; template std::string get_type_name(type_tag) { namespace pf = pretty_function; std::string type = type_name_impl(); return type.substr(pf::PREFIX_LENGTH, type.size() - pf::PREFIX_LENGTH - pf::SUFFIX_LENGTH); } template std::string type_name() { if (std::is_volatile::value) { if (std::is_pointer::value) { return type_name::type>() + " volatile"; } else { return "volatile " + type_name::type>(); } } if (std::is_const::value) { if (std::is_pointer::value) { return type_name::type>() + " const"; } else { return "const " + type_name::type>(); } } if (std::is_pointer::value) { return type_name::type>() + "*"; } if (std::is_lvalue_reference::value) { return type_name::type>() + "&"; } if (std::is_rvalue_reference::value) { return type_name::type>() + "&&"; } return get_type_name(type_tag{}); } inline std::string get_type_name(type_tag) { return "short"; } inline std::string get_type_name(type_tag) { return "unsigned short"; } inline std::string get_type_name(type_tag) { return "long"; } inline std::string get_type_name(type_tag) { return "unsigned long"; } inline std::string get_type_name(type_tag) { return "std::string"; } template std::string get_type_name(type_tag>>) { return "std::vector<" + type_name() + ">"; } template std::string get_type_name(type_tag>) { return "std::pair<" + type_name() + ", " + type_name() + ">"; } template std::string type_list_to_string() { std::string result; auto unused = {(result += type_name() + ", ", 0)..., 0}; static_cast(unused); #if DBG_MACRO_CXX_STANDARD >= 17 if constexpr (sizeof...(T) > 0) { #else if (sizeof...(T) > 0) { #endif result.pop_back(); result.pop_back(); } return result; } template std::string get_type_name(type_tag>) { return "std::tuple<" + type_list_to_string() + ">"; } template inline std::string get_type_name(type_tag>) { return type_name(); } // Implementation of 'is_detected' to specialize for container-like types namespace detail_detector { struct nonesuch { nonesuch() = delete; ~nonesuch() = delete; nonesuch(nonesuch const&) = delete; void operator=(nonesuch const&) = delete; }; template using void_t = void; template class Op, class... Args> struct detector { using value_t = std::false_type; using type = Default; }; template class Op, class... Args> struct detector>, Op, Args...> { using value_t = std::true_type; using type = Op; }; } // namespace detail_detector template