【问题标题】:What serious alternatives exist for the IOStream library? (besides cstdio)IOStream 库有哪些重要的替代方案? (除了 cstdio)
【发布时间】:2011-09-04 12:12:24
【问题描述】:

我正在寻找一个类似于 iostreams 的库,因为它执行转换,并允许写入内存缓冲区、文件和控制台。但是,我想要一些类型安全的东西,就像 iostream 一样。有没有真正的图书馆可以做到这一点?

能够为事物指定输出编码将是一个加分项。

请注意,我对仅将 iostream 放在前面的库不感兴趣,因为它们只会为 iostream 所做的事情增加更多复杂性,例如boost::format.

PreEmptive 评论响应:我不想使用 cstdio,因为使用该系统不可能让代码与输出位置无关。也就是说,您必须调用一个函数将内容发送到缓冲区,并且您必须调用另一个函数将内容发送到文件,以及另一个用于控制台等。

EDIT2:针对下面一连串的 cmets:我受够了 iostreams 和 cstdio。以下是更具体的原因。我试图将我的“咆哮”排除在这个问题之外,但人们一直在问我是否已经摇摆不定,所以这就是我的理由。

cstdio

  • 无法正确处理 Unicode 字符
  • 如果不进行手动缓冲区管理,就无法写入字符串等内容
  • 通常需要支持非标准扩展(例如vsnprintf)才能使用(编辑:好的,现在 C99 的标准库在 C++11 中添加了大部分/所有这些)
  • 在不更改原始代码的情况下无法更改输出位置(非标准扩展,例如在 glibc 中允许您将文件指针视为缓冲区,这是什么...但它仍然只是一个非标准扩展)
  • 让安全变得“有趣”(以至于整个章节都专门在安全文档中解释问题,例如使用“printf”的格式字符串等)
  • 类型不安全

iostreams

  • 对客户来说太复杂了。如果您只使用标准库附带的内容,那就太好了,但尝试扩展内容几乎是不可能的。我阅读了整本“Standard C++ IOStreams and Locales”一书——似乎唯一一本关于该主题的书——两次——但我仍然不知道发生了什么。

我喜欢 iostreams 的概念,甚至是 operator<< 的使用,有些人似乎不喜欢,但对我来说,它似乎完全过度设计了。某人不应该为了成为您图书馆的简单客户而花费无数小时阅读书籍。当然,如果您要添加新的输出源或类似的东西,我可以理解,但是....客户应该避免这种复杂性。 (这不就是图书馆的用途吗?)

这是关于 C++ 中唯一一个在其他编程语言中“正常工作”的痛苦的事情,我认为没有理由变得复杂。

【问题讨论】:

  • 性能原因常常被夸大了——实际上我发现在最近的实现中 iostream 可以胜过 stdio。另一方面,我同意 iostream 的设计不是很好,值得考虑一个更好的替代方案。
  • @Xeo:你要保存流的状态,用那些“哨兵”的东西来处理错误,检查异常说明符来决定是否抛出,不管怎样恢复流的状态什么,等等。我不想那么复杂。
  • +1 好问题,我怀疑你会得到一个好的答案。无论如何,没有什么能让你休息。
  • @Matteo 对于我了解的一点点,boost.iostreams 定义了标准 iostreams 的概念,以便于扩展它们。但我不认为他们修复了格式化输入和格式化输出地狱。
  • @jeffamaphone:是的。我喜欢其他一切——这是我不喜欢的一个特殊的图书馆。 C++ 之所以复杂是因为它很强大——像 STL 这样的很棒的库虽然表明这种复杂性是值得的。当复杂性带来灵活性时,它是值得的;但其他语言的流实现要简单得多,但同样灵活。 (公平地说,C++ 的流几乎早于其他所有人)

标签: c++ iostream


【解决方案1】:

The {fmt} library:我刚从YouTube talk 偶然发现它,它似乎相当不错。

基于 {fmt} 的格式化工具已被提议用于 C++20 中的标准化:P0645。 P0645 和 {fmt} 都使用类似于 Python 的格式字符串语法,它类似于 printf,但使用 {} 作为分隔符而不是 %

例如

#include <fmt/core.h>

int main() {
  fmt::print("The answer is {}.", 42);
}

打印“答案是 42”。到stdout

为 C++20 提议的 std::format 函数:

#include <format>

int main() {
  std::string s = std::format("The answer is {}.", 42);
}

{fmt} 的显着特点:

  1. 在编译时可选地报告格式字符串错误的类型和内存安全。

  2. 可扩展性:用户可以为其类型编写格式化程序,包括自定义格式规范解析器(如在 Python 中)。

  3. 紧凑的二进制代码。上面的打印示例编译为:

    main: # @main
      sub rsp, 24
      mov qword ptr [rsp], 42
      mov rcx, rsp
      mov edi, offset .L.str
      mov esi, 17
      mov edx, 2
      call fmt::v5::vprint(fmt::v5::basic_string_view<char>, fmt::v5::format_args)
      xor eax, eax
      add rsp, 24
      ret
    .L.str:
      .asciz "The answer is {}."
    

    printf 相当,比 iostreams 好得多。

  4. 性能:{fmt} 比printfiostreams 的常见实现要快得多。以下是使用 clang 在 macOS 上进行的 tinyformat 基准测试的结果:

    ================= ============= ===========
    Library           Method        Run Time, s
    ================= ============= ===========
    libc              printf          1.01
    libc++            std::ostream    3.04
    {fmt} 1632f72     fmt::print      0.86
    tinyformat 2.0.1  tfm::printf     3.23
    Boost Format 1.67 boost::format   7.98
    Folly Format      folly::format   2.23
    ================= ============= ===========
    

【讨论】:

  • 感谢您的编辑。是的,图书馆非常棒。
  • 是的,FMT 是类似 iostream 的功能和类似 printf 的语法的完美结合,但据我所知,它没有任何从控制台读取输入的功能。
【解决方案2】:

Boost.Spirit.Qi 用于输入,Boost.Spirit.Karma 用于输出。可以读取/写入任何可以表示为迭代器范围的内容。

【讨论】:

  • 我喜欢这两个库——我不认为它们可以作为 iostream 的通用替代品,因为 1. 与传统库相比,它们的编译时间都非常糟糕,2. 祝你好运调试在发生语法错误时收到的错误消息。对我原来的问题仍然是一个合理的答案,所以 +1。
  • 根据OP,Streams太复杂了,所以现在我们使用Boost Spirit?现在我们有两个问题!
  • @John :据我了解,OP 意味着在易于扩展和运行时复杂性/开销方面很复杂。在这两个方面,Boost.Spirit 都是无与伦比的,所以我支持这个答案。
【解决方案3】:

您可能对Fast Format 库感兴趣。您也可以在他们的网站上查看与其他各种库的比较。

【讨论】:

  • 哇.. 这看起来真的很酷。将不得不玩,看看事情进展如何
  • 遗憾的是,该网站似乎无法正常工作,并且它需要 STLPort,但它的状态似乎不太好。
  • 由于对 STLPort 的依赖(这使我当时无法使用它),我现在取消选中它——我可能会回来再次检查它,但我想要更多使用经验首先是图书馆。 (不过最近缺乏维护并不是一个好兆头)
  • 在其他问题中,它被认为是“alpha”,并且有一个令人震惊的空网站,让我担心未来可能不确定。不错的选择。
  • 这不是 STLPort,它是 STLSoft(不管是什么,它看起来也不是很好)。
【解决方案4】:

使用The fmt libraryThe scn library 怎么样,fmt 可以很好地处理输出,而 scn 可以处理输入。我已经同时使用了这两个库,使用起来比标准库要少得多(而且它是可读的!)。

你应该两个都试试。

【讨论】:

    猜你喜欢
    • 2010-09-28
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-13
    • 1970-01-01
    • 2019-04-14
    相关资源
    最近更新 更多