// // Created by light on 20-1-8. // #ifndef MORDEN_C_OUTPUT_CONTAINER_H #define MORDEN_C_OUTPUT_CONTAINER_H #include // std::ostream #include // std::false_type/true_type/decay_t/is_same_v #include // std::declval/pair // 检测是否是pair template struct is_pair : std::false_type {}; template struct is_pair> : std::true_type {}; template inline constexpr bool is_pair_v = is_pair::value; // 检测输出函数是否存在 template struct has_output_function { template static auto output(U *ptr) -> decltype(std::declval() << *ptr, std::true_type()); template static std::false_type output(...); static constexpr bool value = decltype(output(nullptr))::value; }; template inline constexpr bool has_output_function_v = has_output_function::value; enum CHARS { ORD, // 其他类型 CHAR, // char 类型 STRING // string 类型 }; template int ischarOrString(T &elem) { using std::decay_t; using std::is_same_v; using element_type = decay_t; constexpr bool is_char_v = is_same_v; constexpr bool is_string_v = is_same_v || is_same_v || is_same_v; if (is_char_v) return CHAR; else if (is_string_v) return STRING; else return ORD; } template void output(T &elem, int type, std::ostream &os) { switch (type) { case CHAR: os << '\'' << elem << '\''; break; case STRING: os << '\"' << elem << '\"'; break; case ORD: os << elem; break; } } template auto output_element(std::ostream &os, const T &element, const Cont &) -> typename std::enable_if::value, bool>::type { int ftype = ischarOrString(element.first); int stype = ischarOrString(element.second); output(element.first, ftype, os); os << " => "; output(element.second, stype, os); return true; } template auto output_element(std::ostream &os, const T &element, const Cont &) -> typename std::enable_if::value, bool>::type { int etype = ischarOrString(element); output(element, etype, os); return false; } template std::ostream &operator<<(std::ostream &os, const std::pair &pr) { os << '(' << pr.first << ", " << pr.second << ')'; return os; } // template // auto output_element(std::ostream& os, const T& element, // const Cont&, const std::true_type) //-> decltype(std::declval(), os) //{ // os << element.first << " => " << element.second; // return os; // } // // template // auto output_element(std::ostream& os, const T& element, // const Cont&, ...) //-> decltype(os) //{ // os << element; // return os; // } // 针对没有输出函数的容器处理 template >> auto operator<<(std::ostream &os, const T &container) -> decltype(container.begin(), container.end(), os) { os << "{ "; if (!container.empty()) { bool on_first_element = true; for (auto elem : container) { if (!on_first_element) { os << ", "; } else { on_first_element = false; } output_element(os, elem, container); } } os << " }"; return os; } #endif // MORDEN_C_OUTPUT_CONTAINER_H