istringviewstream 和 outstringstream
文章目录
- **1. `basic_istringviewstream`(输入字符串流)**
- **作用**
- **关键特点**
- **典型用例**
- **2. `basic_outstringstream`(输出字符串流)**
- **作用**
- **关键特点**
- **典型用例**
- **对比标准库的 `istringstream`和 `ostringstream`**
- **总结**
- istringviewstream
- outstringstream
- 测试代码 istringviewstream
- 测试代码 outstringstream
这两个类 basic_istringviewstream
和 basic_outstringstream
都是基于字符串的流类,分别用于输入和输出操作,它们扩展了标准库的流功能,提供了更便捷的字符串处理方式。下面我将分别详细解释它们的作用和特点:
1. basic_istringviewstream
(输入字符串流)
作用
basic_istringviewstream
是一个只读的输入流,它允许你像使用 std::istream
(如 std::istringstream
)一样从字符串或字符缓冲区中读取数据,但它的设计更加高效,特别适合处理字符串视图(string_view
)或原始字符数组。
关键特点
-
基于
string_view
(C++17)或string
(C++11):-
如果编译器支持 C++17,它可以直接包装
std::string_view
,避免额外的字符串拷贝。 -
在 C++11/14 下,它回退到使用
std::string
。
-
-
轻量级,无额外内存分配:
- 它不复制输入数据,而是直接引用现有的字符串或字符缓冲区,因此比
std::istringstream
更高效。
- 它不复制输入数据,而是直接引用现有的字符串或字符缓冲区,因此比
-
支持流式读取:
-
可以使用
>>
操作符按格式提取数据(如int
、float
、string
等)。 -
支持
seekg()
和tellg()
,允许随机访问流中的数据。
-
-
适用于解析字符串数据:
- 适合解析配置文件、网络协议数据、CSV 文件等字符串格式的数据。
典型用例
const char* data = "123 3.14 Hello";
cmn::istringviewstream stream(data, strlen(data));int num;
float pi;
std::string word;stream >> num >> pi >> word; // 解析数据
assert(num == 123);
assert(pi == 3.14f);
assert(word == "Hello");
2. basic_outstringstream
(输出字符串流)
作用
basic_outstringstream
是一个只写的输出流,它允许你像使用 std::ostream
(如 std::ostringstream
)一样向内存缓冲区写入数据,但它的设计更加灵活,支持高效的字符串构建和动态扩容。
关键特点
-
动态缓冲区管理:
-
如果写入的数据超过当前缓冲区大小,它会自动扩容(类似于
std::vector
的增长策略)。 -
可以预分配缓冲区(
reserve
),减少扩容带来的性能开销。
-
-
支持移动语义:
- 允许从现有
std::string
移动构造,避免额外的拷贝。
- 允许从现有
-
提供多种获取数据的方式:
-
take_str()
:获取字符串并清空流(转移所有权,避免拷贝)。 -
str()
(C++17):返回string_view
,避免拷贝。 -
data()
:直接访问底层字符数组(类似std::string::data()
)。
-
-
适用于高效构建字符串:
-
比
sprintf
或手动字符串拼接更安全、更高效。 -
适合日志记录、JSON/XML 生成、网络数据打包等场景。
-
典型用例
cmn::outstringstream stream;
stream << "User: " << "Alice" << ", Age: " << 25;// 获取字符串(移动语义,避免拷贝)
std::string result = stream.take_str();
assert(result == "User: Alice, Age: 25");// 或者直接访问数据(不转移所有权)
const char* data = stream.data();
std::cout << data << std::endl;
**对比标准库的 istringstream
和 ostringstream
**
特性 | basic_istringviewstream | std::istringstream |
---|---|---|
数据来源 | string_view 或原始字符数组 | 必须使用 std::string |
内存开销 | 无额外拷贝(仅引用) | 需要拷贝字符串 |
性能 | 更高(无动态分配) | 稍低(需要构造字符串) |
特性 | basic_outstringstream | std::ostringstream |
------ | ------------------------ | ---------------------- |
缓冲区管理 | 动态扩容(类似 vector ) | 依赖实现,可能频繁分配 |
获取数据方式 | take_str() (移动)、data() (直接访问) | 仅 str() (可能拷贝) |
适用场景 | 高性能字符串构建 | 通用字符串流 |
总结
-
**
basic_istringviewstream
:适用于高效解析字符串数据**,特别适合处理string_view
或原始字符数组,避免不必要的拷贝。 -
**
basic_outstringstream
:适用于高效构建字符串**,支持动态扩容和移动语义,比std::ostringstream
更灵活。
这两个类在需要高性能字符串处理的场景(如网络通信、日志系统、数据解析/生成)中非常有用,尤其是当你想避免不必要的内存分配和拷贝时。
istringviewstream
#ifndef INPUT_STRING_VIEW_STREAM_H
#define INPUT_STRING_VIEW_STREAM_H
#pragma once/*** MIT许可证** 版权所有 (c) 2021 Francesco Pretto** 以下为许可证全文...*/// 包含标准库头文件
#include <istream> // 标准输入流
#include <streambuf> // 流缓冲区基类
#include <string> // 字符串类
#if __cplusplus >= 201703L
#include <string_view> // C++17引入的字符串视图
#endif // __cplusplus >= 201703Lnamespace cmn
{// 基于Stack Overflow实现的字符串视图缓冲区模板类template <typename CharT>class stringviewbuffer : public std::basic_streambuf<CharT>{public:// 定义类型别名using traits_type = std::char_traits<CharT>;using int_type = typename traits_type::int_type;using pos_type = typename traits_type::pos_type;using off_type = typename traits_type::off_type;public:// 默认构造函数stringviewbuffer(): m_begin(nullptr), m_end(nullptr), m_current(nullptr){}// 拷贝构造函数和赋值运算符stringviewbuffer(const stringviewbuffer&) = default;stringviewbuffer& operator=(const stringviewbuffer&) = default;// 从字符指针和大小构造stringviewbuffer(const CharT* buffer, size_t size): m_begin(buffer), m_end(buffer + size), m_current(buffer){}#if __cplusplus >= 201703L// C++17及以上版本:从string_view构造stringviewbuffer(const std::basic_string_view<CharT>& view): m_begin(view.data()), m_end(view.data() + view.size()), m_current(view.data()){}
#else// C++17以下版本:从string构造stringviewbuffer(const std::basic_string<CharT>& str): m_begin(str.data()), m_end(str.data() + str.size()), m_current(str.data()){}
#endif // __cplusplus >= 201703Lpublic:// 设置缓冲区内容(字符指针和大小)void str(const CharT* buffer, size_t size){std::basic_streambuf<CharT>::setg(nullptr, nullptr, nullptr);std::basic_streambuf<CharT>::setp(nullptr, nullptr);m_begin = buffer;m_end = buffer + size;m_current = buffer;}#if __cplusplus >= 201703L// C++17及以上版本:从string_view设置内容void str(const std::basic_string_view<CharT>& view){str(view.data(), view.size());}
#else// C++17以下版本:从string设置内容void str(const std::basic_string<CharT>& str){str(view.data(), view.size());}
#endif // __cplusplus >= 201703Lprotected:// 实现streambuf虚函数:查看下一个字符但不移动指针int_type underflow() override{if (m_current == m_end)return traits_type::eof();return traits_type::to_int_type(*m_current);}// 实现streambuf虚函数:读取下一个字符并移动指针int_type uflow() override{if (m_current == m_end)return traits_type::eof();return traits_type::to_int_type(*m_current++);}// 实现streambuf虚函数:回退一个字符int_type pbackfail(int_type ch) override{// 只允许回退已存在的字符if (m_current == m_begin || (ch != traits_type::eof() && ch != m_current[-1]))return traits_type::eof();return traits_type::to_int_type(*--m_current);}// 实现streambuf虚函数:绝对定位pos_type seekpos(std::streampos sp, std::ios_base::openmode which) override{(void)which;const CharT* current = m_begin + (std::streamoff)sp;if (current < m_begin || current > m_end)return pos_type(off_type(-1));m_current = current;return m_current - m_begin;}// 实现streambuf虚函数:相对定位std::streampos seekoff(std::streamoff off, std::ios_base::seekdir way,std::ios_base::openmode which) override{(void)which;const CharT* current = m_current;if (way == std::ios_base::beg){current = m_begin + off;}else if (way == std::ios_base::cur){current += off;}else if (way == std::ios_base::end){current = m_end + off;}if (current < m_begin || current > m_end)return pos_type(off_type(-1));m_current = current;return m_current - m_begin;}// 实现streambuf虚函数:获取剩余字符数量std::streamsize showmanyc() override{return m_end - m_current;}private:// 缓冲区起始指针const CharT* m_begin;// 缓冲区结束指针const CharT* m_end;// 当前读取位置指针const CharT* m_current;};// 字符串视图输入流模板类template <typename CharT>class basic_istringviewstream : public std::basic_istream<CharT>{public:// 默认构造函数basic_istringviewstream(): std::basic_istream<CharT>(nullptr){this->rdbuf(&m_buf);}// 从字符指针和大小构造basic_istringviewstream(const CharT* buffer, size_t size): std::basic_istream<CharT>(nullptr), m_buf(buffer, size){this->rdbuf(&m_buf);}#if __cplusplus >= 201703L// C++17及以上版本:从string_view构造basic_istringviewstream(const std::basic_string_view<CharT>& view): std::basic_istream<CharT>(nullptr), m_buf(view){this->rdbuf(&m_buf);}
#else// C++17以下版本:从string构造basic_istringviewstream(const std::basic_string<CharT>& str): std::basic_istream<CharT>(nullptr), m_buf(str){this->rdbuf(&m_buf);}
#endif // __cplusplus >= 201703Lpublic:// 设置流内容(字符指针和大小)void str(const CharT* buffer, size_t size){m_buf.str(buffer, size);}#if __cplusplus >= 201703L// C++17及以上版本:从string_view设置内容void str(const std::basic_string_view<CharT>& view){m_buf.str(view);}
#else// C++17以下版本:从string设置内容void str(const std::basic_string<CharT>& str){m_buf.str(str);}
#endif // __cplusplus >= 201703Lprivate:// 字符串视图缓冲区实例stringviewbuffer<CharT> m_buf;};// 常用字符类型别名using istringviewstream = basic_istringviewstream<char>;using wistringviewstream = basic_istringviewstream<wchar_t>;
}#endif // INPUT_STRING_VIEW_STREAM_H
outstringstream
#ifndef OUT_STRING_STREAM_H
#define OUT_STRING_STREAM_H
#pragma once/*** MIT许可证** 版权所有 (c) 2021 Francesco Pretto** 以下是完整的MIT许可证文本...*/// 包含必要的标准库头文件
#include <cstdlib> // C标准库,包含内存管理等函数
#include <limits> // 数值极限相关定义
#include <ostream> // 标准输出流
#include <string> // 字符串类
#if __cplusplus >= 201703L
#include <string_view> // C++17引入的字符串视图
#endifnamespace cmn
{// 基于Kuba在Stack Overflow上的实现,创建输出字符串流模板类template <typename CharT>class basic_outstringstream : public std::basic_ostream<CharT, std::char_traits<CharT>>{// 定义类型别名using traits_type = std::char_traits<CharT>;using base_stream_type = std::basic_ostream<CharT, traits_type>;// 内部缓冲区类,继承自基本流缓冲区class buffer : public std::basic_streambuf<CharT, std::char_traits<CharT>>{// 定义基类类型和内部类型using base_buf_type = std::basic_streambuf<CharT, traits_type>;using int_type = typename base_buf_type::int_type;private:// 安全地移动缓冲区指针,处理大偏移量void safe_pbump(std::streamsize off){// 由于pbump不支持64位偏移量,需要分段处理// 参考GCC bug #47921int maxbump;if (off > 0)maxbump = std::numeric_limits<int>::max(); // 正方向最大偏移else if (off < 0)maxbump = std::numeric_limits<int>::min(); // 负方向最大偏移else // == 0return;// 分段处理大偏移量while (std::abs(off) > std::numeric_limits<int>::max()){this->pbump(maxbump);off -= maxbump;}// 处理剩余偏移量this->pbump((int)off);}// 初始化缓冲区void init(){// 设置缓冲区起始和结束指针this->setp(const_cast<CharT*>(m_str.data()),const_cast<CharT*>(m_str.data()) + m_str.size());// 将指针移动到字符串末尾this->safe_pbump((std::streamsize)m_str.size());}protected:// 缓冲区溢出处理函数(当缓冲区满时调用)int_type overflow(int_type ch) override{// 如果是EOF字符,直接返回非EOFif (traits_type::eq_int_type(ch, traits_type::eof()))return traits_type::not_eof(ch);// 如果字符串为空,初始化为1个字符大小if (m_str.empty())m_str.resize(1);else// 否则双倍扩容m_str.resize(m_str.size() * 2);// 保存当前大小size_t size = this->size();// 重新设置缓冲区指针this->setp(const_cast<CharT*>(m_str.data()),const_cast<CharT*>(m_str.data()) + m_str.size());// 恢复指针位置this->safe_pbump((std::streamsize)size);// 写入新字符*this->pptr() = traits_type::to_char_type(ch);// 移动指针this->pbump(1);return ch;}public:// 构造函数:预分配指定大小的缓冲区buffer(std::size_t reserveSize){m_str.reserve(reserveSize);init();}// 构造函数:移动已有字符串buffer(std::basic_string<CharT>&& str): m_str(std::move(str)){init();}// 构造函数:拷贝已有字符串buffer(const std::basic_string<CharT>& str): m_str(str){init();}public:// 获取当前缓冲区中数据的大小size_t size() const{return (size_t)(this->pptr() - this->pbase());}#if __cplusplus >= 201703L// C++17及以上版本:获取字符串视图std::basic_string_view<CharT> str() const{return std::basic_string_view<CharT>(m_str.data(), size());}
#endif// 获取并转移字符串所有权std::basic_string<CharT> take_str(){// 调整字符串大小为实际使用的大小m_str.resize(size());// 移动字符串std::string ret = std::move(m_str);// 重新初始化缓冲区init();return ret;}// 清空缓冲区void clear(){m_str.clear();init();}// 获取数据指针const CharT* data() const{return m_str.data();}private:// 内部存储的字符串std::basic_string<CharT> m_str;};public:// 构造函数:默认预分配8字节explicit basic_outstringstream(std::size_t reserveSize = 8): base_stream_type(nullptr), m_buffer(reserveSize){this->rdbuf(&m_buffer);}// 构造函数:移动已有字符串explicit basic_outstringstream(std::basic_string<CharT>&& str): base_stream_type(nullptr), m_buffer(str){this->rdbuf(&m_buffer);}// 构造函数:拷贝已有字符串explicit basic_outstringstream(const std::basic_string<CharT>& str): base_stream_type(nullptr), m_buffer(str){this->rdbuf(&m_buffer);}#if __cplusplus >= 201703L// C++17及以上版本:获取字符串视图std::basic_string_view<CharT> str() const{return m_buffer.str();}
#endif// 获取并转移字符串所有权std::basic_string<CharT> take_str(){return m_buffer.take_str();}// 获取数据指针const CharT* data() const{return m_buffer.data();}// 获取当前数据大小size_t size() const{return m_buffer.size();}// 清空流void clear(){m_buffer.clear();}private:// 内部缓冲区实例buffer m_buffer;};// 常用字符类型别名using outstringstream = basic_outstringstream<char>;using woutstringstream = basic_outstringstream<wchar_t>;
}#endif // OUT_STRING_STREAM_H
测试代码 istringviewstream
#include "istringviewstream.h"
#include <cassert>
#include <iostream>
#include <sstream>
#include <string>
// 测试从char类型缓冲区读取数据的功能
void test_char_buffer() {// 准备测试用的C风格字符串const char* test_str = "Hello, World!";// 创建字符串视图流对象,传入字符串和长度cmn::istringviewstream stream(test_str, strlen(test_str));std::string result;// 从流中读取第一个单词stream >> result;// 验证读取结果是否正确assert(result == "Hello,");// 从流中读取第二个单词stream >> result;// 验证读取结果是否正确assert(result == "World!");// 测试EOF(文件结束)标志char c;stream >> c;// 验证流是否到达结尾assert(stream.eof());
}// 测试从wchar_t类型缓冲区读取数据的功能
void test_wchar_buffer() {// 准备测试用的宽字符字符串const wchar_t* test_str = L"宽字符 测试";// 创建宽字符字符串视图流对象cmn::wistringviewstream stream(test_str, wcslen(test_str));std::wstring result;// 读取第一个宽字符单词stream >> result;// 验证读取结果assert(result == L"宽字符");// 读取第二个宽字符单词stream >> result;// 验证读取结果assert(result == L"测试");
}// 测试C++17的string_view支持
void test_string_view_cpp17() {// 只在C++17及以上版本编译
#if __cplusplus >= 201703L// 创建string_view对象std::string_view view("C++17 string_view test");// 使用string_view构造流对象cmn::istringviewstream stream(view);std::string part1, part2;// 从流中读取两个单词stream >> part1 >> part2;// 验证第一个单词assert(part1 == "C++17");// 验证第二个单词assert(part2 == "string_view");
#endif
}// 测试C++11的string支持
void test_string_cpp11() {// 创建标准字符串对象std::string str("C++11 string test");// 使用string构造流对象cmn::istringviewstream stream(str);std::string part1, part2;// 从流中读取两个单词stream >> part1 >> part2;// 验证第一个单词assert(part1 == "C++11");// 验证第二个单词assert(part2 == "string");
}// 测试流的定位功能(seek和tell)
void test_seek_and_tell() {// 准备测试字符串const char* test_str = "Seek and Tell test";// 创建流对象cmn::istringviewstream stream(test_str, strlen(test_str));// 验证初始位置是否为0assert(stream.tellg() == 0);std::string word;// 读取第一个单词stream >> word;// 验证读取结果assert(word == "Seek");// 验证当前位置是否正确assert(stream.tellg() == 4); // "Seek" + space// 跳转到指定位置stream.seekg(10, std::ios::beg);// 读取当前位置的单词stream >> word;// 验证读取结果assert(word == "Tell");// 相对当前位置回退stream.seekg(-5, std::ios::cur);// 再次读取单词stream >> word;// 验证读取结果assert(word == "Tell");
}// 测试空流的行为
void test_empty_stream() {// 创建默认构造的空流cmn::istringviewstream empty_stream;// 验证是否立即到达EOFassert(empty_stream.eof());// 创建包含空字符串的流const char* empty_str = "";cmn::istringviewstream empty_stream2(empty_str, 0);// 验证是否到达EOFassert(empty_stream2.eof());char c;// 尝试从空流读取字符empty_stream2 >> c;// 验证读取是否失败assert(empty_stream2.fail());
}// 测试重用流对象的功能
void test_reuse_stream() {// 创建默认流对象cmn::istringviewstream stream;// 设置第一个测试字符串const char* str1 = "First string";stream.str(str1, strlen(str1));std::string part1, part2;// 读取两个单词stream >> part1 >> part2;// 验证第一个单词assert(part1 == "First");// 验证第二个单词assert(part2 == "string");// 设置第二个测试字符串const char* str2 = "Second string";stream.str(str2, strlen(str2));// 再次读取两个单词stream >> part1 >> part2;// 验证第一个单词assert(part1 == "Second");// 验证第二个单词assert(part2 == "string");
}// 测试各种边界情况
void test_edge_cases() {// 测试单字字符串const char* single_word = "Single";cmn::istringviewstream stream1(single_word, strlen(single_word));std::string word;stream1 >> word;// 验证读取结果assert(word == "Single");// 验证是否到达EOFassert(stream1.eof());// 测试只有空格的字符串const char* spaces = " ";cmn::istringviewstream stream2(spaces, strlen(spaces));stream2 >> word;// 验证是否读取失败assert(word.empty());// 验证流状态是否为failassert(stream2.fail());// 测试超长字符串std::string long_str(1000, 'a');long_str[500] = ' ';cmn::istringviewstream stream3(long_str.c_str(), long_str.size());stream3 >> word;// 验证前半部分读取正确assert(word.size() == 500);stream3 >> word;// 验证后半部分读取正确assert(word.size() == 499);
}// 主测试函数
int main() {// 执行所有测试用例test_char_buffer();test_wchar_buffer();test_string_view_cpp17();test_string_cpp11();test_seek_and_tell();test_empty_stream();test_reuse_stream();test_edge_cases();// 所有测试通过后输出成功信息std::cout << "All tests passed successfully!" << std::endl;return 0;
}
测试代码 outstringstream
#include "out_string_stream.h" // 包含自定义的输出字符串流头文件
#include <cassert> // 断言库,用于验证测试条件
#include <iostream> // 标准输入输出流
#include <string> // 字符串类// 测试基本输出功能
void test_basic_output() {// 创建输出字符串流对象cmn::outstringstream stream;// 向流中输出多个字符串片段stream << "Hello";stream << ", ";stream << "World";stream << "!";// 获取并转移流中的字符串std::string result = stream.take_str();// 验证输出结果是否正确assert(result == "Hello, World!");// 打印测试通过信息std::cout << "test_basic_output passed: " << result << std::endl;
}// 测试预分配缓冲区功能
void test_reserved_output() {// 创建预分配100字节缓冲区的输出流cmn::outstringstream stream(100);// 向流中输出数据stream << "This is a test";stream << " of reserved buffer";// 验证流中数据大小是否正确assert(stream.size() == strlen("This is a test of reserved buffer"));// 获取并验证流内容std::string result = stream.take_str();assert(result == "This is a test of reserved buffer");std::cout << "test_reserved_output passed: " << result << std::endl;
}// 测试移动构造函数
void test_move_construction() {// 准备初始字符串std::string initial = "Initial content";// 使用移动构造创建输出流cmn::outstringstream stream(std::move(initial));// 向流中追加内容stream << " with additional content";// 获取并验证结果std::string result = stream.take_str();assert(result == "Initial content with additional content");std::cout << "test_move_construction passed: " << result << std::endl;
}// 测试拷贝构造函数
void test_copy_construction() {// 准备初始字符串std::string initial = "Initial content";// 使用拷贝构造创建输出流cmn::outstringstream stream(initial);// 向流中追加内容stream << " with additional content";// 获取并验证结果std::string result = stream.take_str();assert(result == "Initial content with additional content");// 验证原始字符串未被修改assert(initial == "Initial content");std::cout << "test_copy_construction passed: " << result << std::endl;
}// 测试大量数据输出
void test_large_output() {// 创建输出流cmn::outstringstream stream;const int count = 10000; // 测试数据量// 向流中输出大量数据for (int i = 0; i < count; ++i) {stream << i << " ";}// 获取并验证结果std::string result = stream.take_str();assert(result.size() > 0);// 验证包含最后一个数字assert(result.find("9999 ") != std::string::npos);std::cout << "test_large_output passed with " << count << " numbers" << std::endl;
}// 测试清空流功能
void test_clear() {// 创建输出流并输出内容cmn::outstringstream stream;stream << "Some content";assert(stream.size() > 0);// 清空流stream.clear();assert(stream.size() == 0);// 重新输出并验证stream << "New content";std::string result = stream.take_str();assert(result == "New content");std::cout << "test_clear passed: " << result << std::endl;
}// 测试C++17 string_view功能
void test_string_view_cpp17() {
// 仅在C++17及以上版本编译
#if __cplusplus >= 201703L// 创建输出流并输出内容cmn::outstringstream stream;stream << "C++17 string_view test";// 获取string_view并验证std::string_view view = stream.str();assert(view == "C++17 string_view test");std::cout << "test_string_view_cpp17 passed: " << view << std::endl;
#endif
}// 测试宽字符流功能
void test_wide_char_stream() {// 创建宽字符输出流cmn::woutstringstream stream;// 输出宽字符和数字stream << L"宽字符测试 ";stream << 12345;// 获取并验证结果std::wstring result = stream.take_str();assert(result == L"宽字符测试 12345");std::wcout << L"test_wide_char_stream passed: " << result << std::endl;
}// 测试数据指针访问功能
void test_data_access() {// 创建输出流并输出内容cmn::outstringstream stream;stream << "Data access test";// 获取数据指针并验证内容const char* data = stream.data();assert(strncmp(data, "Data access test", stream.size()) == 0);std::cout << "test_data_access passed: " << data << std::endl;
}// 测试多次获取字符串功能
void test_multiple_take() {// 创建输出流cmn::outstringstream stream;// 第一次输出并获取stream << "First part";std::string part1 = stream.take_str();assert(part1 == "First part");// 第二次输出并获取stream << "Second part";std::string part2 = stream.take_str();assert(part2 == "Second part");std::cout << "test_multiple_take passed: " << part1 << " | " << part2 << std::endl;
}// 测试空流功能
void test_empty_stream() {// 创建空输出流cmn::outstringstream stream;assert(stream.size() == 0);// 获取空字符串std::string empty = stream.take_str();assert(empty.empty());std::cout << "test_empty_stream passed" << std::endl;
}// 主测试函数
int main() {// 执行所有测试用例test_basic_output();test_reserved_output();test_move_construction();test_copy_construction();test_large_output();test_clear();test_string_view_cpp17();test_wide_char_stream();test_data_access();test_multiple_take();test_empty_stream();// 所有测试通过后输出成功信息std::cout << "All tests passed successfully!" << std::endl;return 0;
}