如何实现类似Python的C++通用打印函数(支持多维容器)
实现任意维度容器的通用打印函数
要实现支持任意维度vector(甚至其他标准容器)的打印,不用手动为每一层嵌套写重载,核心思路是利用模板递归+类型判断,自动识别容器和普通类型,逐层处理。
完整实现代码(C++17及以上)
#include <iostream> #include <vector> #include <array> #include <string> #include <type_traits> // 辅助类型判断:检测是否为可遍历容器(存在begin/end成员) template<typename T, typename = void> struct is_container : std::false_type {}; template<typename T> struct is_container<T, std::void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>> : std::true_type {}; template<typename T> constexpr bool is_container_v = is_container<T>::value; // 打印普通类型(非容器) template<typename T> std::enable_if_t<!is_container_v<T>> print(const T& value) { std::cout << value << ' '; } // 打印容器类型:递归遍历每个元素 template<typename Container> std::enable_if_t<is_container_v<Container>> print(const Container& container) { for (const auto& elem : container) { print(elem); } std::cout << '\n'; } // 单独处理字符串:避免被拆分为字符逐个打印 void print(const std::string& str) { std::cout << str << '\n'; } int main() { std::vector<int> vec1{1, 2, 3, 4, 5}; std::vector<std::vector<double>> vec2{{1.1, 2.2}, {3.3, 4.4}}; std::vector<std::vector<std::vector<char>>> vec3{{{'a', 'b'}, {'c', 'd'}}, {{'e', 'f'}, {'g', 'h'}}}; // 测试4维vector std::vector<std::vector<std::vector<std::vector<int>>>> vec4{{{{1,2}, {3,4}}, {{5,6}, {7,8}}}, {{{9,10}, {11,12}}, {{13,14}, {15,16}}}}; // 测试std::array std::array<std::array<int, 2>, 2> arr{{{1,2}, {3,4}}}; std::string str = "Hello, C++!"; print(vec1); print(vec2); print(vec3); print(vec4); print(arr); print(str); return 0; }
关键逻辑说明
容器类型判断:
用std::void_t(C++17引入)实现SFINAE,判断类型是否拥有begin()和end()成员,以此识别可遍历容器。这种方式兼容vector、array、list等绝大多数标准容器。递归打印:
- 对于非容器类型(如int、double、char),直接打印值;
- 对于容器类型,遍历每个元素并递归调用
print,自动逐层拆解嵌套容器,直到最内层的普通类型。这样不管是3维、4维还是更高维度的容器,都能自动处理。
字符串特殊处理:
因为std::string也满足容器的判断条件,若不单独重载,会被拆成单个字符打印。单独写一个print函数处理字符串,直接输出完整内容并换行,符合预期行为。
C++20简化版本(用Concept)
如果使用C++20,可通过Concept替代SFINAE,代码更简洁直观:
#include <iostream> #include <vector> #include <array> #include <string> #include <concepts> // 定义Iterable概念:拥有begin/end的类型 template<typename Container> concept Iterable = requires(Container c) { std::begin(c); std::end(c); }; // 打印普通类型 template<typename T> void print(const T& value) requires (!Iterable<T>) { std::cout << value << ' '; } // 打印容器类型 template<Iterable Container> void print(const Container& container) { for (const auto& elem : container) { print(elem); } std::cout << '\n'; } // 字符串处理重载 void print(const std::string& str) { std::cout << str << '\n'; } // main函数同前,略
内容的提问来源于stack exchange,提问作者Zohaib Hamdule
相关产品推荐
相关产品推荐

