text formatting
这一部分是对格式化输出的扩展,并增加了std:format一系列函数,感觉与C#相当类似(穿越了?)。对某一类型,其占位符(替换符)的格式如下:
{n:arg-id}
其中n代表后面参数的index,终于可以占位符的顺序与参数顺序不同了,也可以重复输出某参数了,n也可以是一个名字,绑定后面的参数,以实现命名参数输出,arg-id的规则比较复杂,与原先的format string类似。
以下是几个例子:
位置对应输出:print("I'd rather be {1} than {0}.\n", "right", "happy");
命名对应输出:print("Hello, {name}! The answer is {number}. Goodbye, {name}.\n",arg("name", name), arg("number", number));
print("Padding:\t{:05.2f} {:.2f} {:5.2f}\n", 1.5, 1.5, 1.5);
print("Decimal:\t{} {} {:06} {} {:0} {:+} {:d}\n", 1, 2, 3, 0, 0, 4, -1);
auto s6 = std::format("{:{}.{}f}", pi, 10, 5); // s6 = " 3.14000" (width = 10, precision = 5)
【由于GCC10.2并无<format>,因此上述代码的编译还有待时日。】
其实最大的变化就是format string中占位符的数量和位置与后面参数的数量和位置不需要一定相同了。
上面std::format采用了变长模板参数,采用同样的方法,也可以写我们自己的format parser,用于自定义类型的输出。
Synchronized output
在新增的<syncstream>,定义了两个模板类std::basic_syncbuf和basic_osyncstream。std::basic_syncbuf实际上是对std::basic_streambuf再包装(实现上是共有继承std::basic_streambuf)。它内部有缓存区,具有两个特性:
- 搜集(暂存)输入,当flush或析构时,整体输出,这大概是它名字的由来;
- 向它输入时,数据不会发生“竞争”,即不同线程的输入字符串不会出现交叉(这种现象在std:cout上会发生)
一般我们使用两个特化的类syncbuf(即basic_syncbuf<char>)和wsyncbuf(即 basic_syncbuf<wchar_t>)
basic_osyncstream是对std::basic_syncbuf的再包装,我们一般使用的也是它的两个特化类:osyncstream(即basic_osyncstream<char>)和wosyncstream (即basic_osyncstream<wchar_t>)。
一个大致的示例如下,在线程1,2中同时输出一段文字:
std::thread th1([](){
std::osyncstream synced_out(std::cout);
synced_out << "Hello, World!, \n”<<”This is a demonstration of osyncstream\n”;}
std::thread th2([](){
std::osyncstream synced_out(std::cout);
synced_out << "Hello, World!, \n”<<”This is a demonstration of osyncstream\n”;}
如果直接采用std::cout,在最终的显示结果中,它们很有可能出现文字交叠,即发生了数据同一资源(std::cout)上的竞争,而采用了std::osyncstream后,就不会发生了。
【由于GCC10.2没有对<syncstream>的支持,上面示例目前还不能运行。】
本文介绍了C++的新特性,包括std::format的格式化输出,允许占位符顺序与参数顺序不一致,支持命名参数,以及std::syncstream中的同步流buf和osyncstream,确保多线程输出时不发生数据竞争。示例展示了这些新功能的使用,强调了它们在并发输出场景中的优势。
1057

被折叠的 条评论
为什么被折叠?



