C++:使用 std::cin 的多个副本?

C++: working with multiple copies of std::cin?

我正在编写一个简单的通用解析器组合器库。这意味着该库包含许多称为解析器的小函数对象,它们(在调用时)将字符串作为输入并 return ParseResults 列表作为输出,其中 ParseResult 是

template <typename A> using ParseResult = std::pair<A, std::string> 如果解析器不匹配,列表为空,如果匹配则包含单个结果,并且某些可能以多种(不明确)方式匹配的解析器可能 return 更多结果。

但是,这意味着现在正在进行大量的字符串复制。此外,在开始时,最终构造的解析器需要使用字符串来调用,因此所有 std::cin (或文件的竞争内容)都被复制到字符串中。

似乎更好的主意(因为解析器只查看字符串当前前面的第一个(几个)字符),跟踪您现在在标准中的位置输入流。我相信这正是 std::istream 的含义。但是,istream 是不可复制的。如何解决我的问题? 有没有办法 return 一个 istream 的副本,它指向原始指向的地方后面的几个字符?还是有另一种更简洁的方法来解决这个问题?

问题可以这样改写:如何以一种避免过度复制并允许输入流的方式表示输入的未解析部分?

最灵活的方式是用迭代器来表示。如果解析器进行回溯,则需要 ForwardIterator,否则 InputIterator 就足够了。这意味着您可以直接在 std::cinstd::ifstream 上使用 std::istream_iterator,或者从内存中的 std::stringschar 数组进行解析。带回溯的流式传输有点复杂,需要您编写一个缓冲迭代器适配器,将 InputIteratorstd::istream_iterator 转换成 ForwardIterator 或编写一个迭代器直接包装 std::ifstream 和当你需要回溯时做 .seekg()

另一种选择是使用 C++17 的 std::string_view,它不会复制并且有一个很好的、易于解析的界面。这并不能解决流式传输问题,您仍然必须先读取整个文件。