C++中的std::print(C++23)是什么?(如何替代繁琐的cout和printf)

2次阅读

std::printc++23 引入的类型安全格式化输出函数,但截至 2024 年中主流编译器尚未默认支持:GCC 13 不支持,Clang 18 需手动开启 -std=c++2b 且 libc++ 实现未完成,MSVC 2022 17.8+ 仅部分支持。

C++中的std::print(C++23)是什么?(如何替代繁琐的cout和printf)

std::print 是什么,现在能用吗

std::print 是 C++23 引入的格式化输出函数,目标是替代 std::cout 的链式拼接和 printf 的类型不安全。但它不是“开箱即用”的——目前(截至 2024 年中)主流编译器尚未默认启用:GCC 13 默认不支持,Clang 18 需手动开启 -std=c++2b 且依赖 libc++ 实现未完成,MSVC 2022 17.8+ 仅部分支持(需 /std:c++23 + 启用预览特性)。实际项目中直接依赖 std::print 很可能编译失败。

为什么不能直接用 printf 或 cout 替代它

printf 安全隐患明确:printf("%s", nullptr) 崩溃、参数类型错位无编译期检查;std::cout 则是另一类麻烦:操作符重载导致模板推导复杂、流状态(如 std::hex)易污染后续输出、性能上每次 std::print 设计为零状态、类型安全、一次解析格式串——但前提是你的标准库实现了它。当前更现实的选择是:

  • 短期:用 fmt::printfmt 库),API 几乎与 std::print 一致,C++17 起可用,已被 GCC/Clang/MSVC 广泛集成
  • 过渡期:若必须用标准库,可封装一层 std::ostringstream + std::format(C++20),再输出到 std::cout,但多一次字符串拷贝

怎么写一个临时替代 std::print 的宏或函数

如果不想引入第三方库,又想快速获得类似体验,可以基于 std::format(C++20)手写一个轻量封装:

#include  #include  

template void print(std::string_view fmt, Args&&... args) { std::cout << std::vformat(fmt, std::make_format_args(args...)); }

注意几个坑:

立即学习C++免费学习笔记(深入)”;

  • std::format 不支持 %d 这类 C 风格占位符,必须用 {}{0}{1}
  • std::vformat 抛异常(std::format_error)当格式串非法,线上代码建议加 try/catch
  • std::make_format_args 要求所有参数可被格式化(比如裸指针不行,得转 static_cast(p)
  • 没有 std::printstd::print(stderr, ...) 变体,如需重定向得自己传流对象

std::print 和 fmt::print 的行为差异有哪些

虽然 fmt::print 是事实上的 std::print 参考实现,但仍有细节差别:

  • fmt::print 支持编译期格式串检查(fmt::print(FMT_STRING("x = {}"), 42)),std::print 标准未强制要求
  • fmt::print 默认启用颜色、对齐等扩展功能;std::print 严格按标准只做基础格式化
  • windowsfmt::print 自动处理换行符(nrn),std::print 不处理,依赖底层流
  • fmt::print 可直接格式化 std::Filesystem::path 等自定义类型(通过特化 fmt::formatter),std::print 仅支持标准库定义的格式化类型

真正要用上 std::print,得盯住 libc++ 和 libstdc++ 的实现进度,而不是只看编译器版本号。现在写 demo 可以玩,进生产还得掂量下工具链成熟度。

text=ZqhQzanResources