`basic_streambuf :: setbuf`的效果

时间:2010-12-03 20:53:40

标签: c++ c++11 language-lawyer

我的问题如下:Martin York thisthisthis答案中的{{3}}声明可以从某个部分读取stringstream使用basic_stringbuf::pubsetbuf这样的内存:

char buffer[] = "123";
istringstream in;
in.rdbuf()->pubsetbuf(buffer, sizeof(buffer)); // calls basic_stringbuf::setbuf
int num;
in >> num; // reads 123

不幸的是,我挖掘了整个标准,无法确定它在哪里工作。我看到的只是实现定义。事实上,在微软的实施上(也许在其他人的实施上),这个电话没有效果。

以下是我在上一篇C ++ 0x草案中找到的相关引文。对于basic_streambuf::setbuf [streambuf.virt.buffer]:

  

1 效果:以本条款(27.8.1.4,27.9.1.5)中从basic_streambuf派生的每个类别单独定义的方式影响流缓冲。

     

2 默认行为: 什么都不做。返回此。

然而,在派生类中,它似乎离开了行为实现定义。对于basic_stringbuf::setbuf,它说[stringbuf.virtuals]:

  

1 效果: 实现定义,但setbuf(0,0)无效。

对于basic_filebuf::setbuf,它说[filebuf.virtuals]:

  

12 效果:如果是setbuf(0,0)[...],则流变为无缓冲。否则结果是实现定义。 “无缓冲”[...]

就是这样。因此,正如我所看到的,一个有效的实现可以完全忽略这些调用(对于非null参数)。

我错了吗?这个标准的正确解释是什么? C ++ 98/03 / 0x有相同的保证吗?您是否有更多关于上述代码的哪些实现以及不适用的实现的统计信息?如何使用basic_streambuf::setbuf

2 个答案:

答案 0 :(得分:8)

我认为它是实现定义的,并且您提供了相关的引号。

为了记录,这是Standard C++ IOStreams and locales,而不是最近我不得不承认的一本书,在标题为“几乎无语义的函数 - {{1} } “:

  

虚拟成员函数setbuf()   是一个相当奇特的流缓冲区   会员。 它的语义基本上是   未定义即可。对于字符串流缓冲区,   setbuf()的语义是   实现定义,除了   定义setbuf():if   在流上调用setbuf(0, 0)   之前和I / O已经发生了   流,流变为无缓冲,   这意味着角色是直接的   运送到文件和从文件传输   系统。 否则,结果是   实现定义

     但是,规格   setbuf(0, 0)setbuf() {。}}   basic_filebuf几乎没有强加任何东西   关于语义的要求   其他流缓冲区中的basic_stringbuf   类型。充其量,一般语义   可以定义为设备,并在   用户定义的流缓冲区的情况   类型,特定于实现。

     

缺乏任何要求会让您失望   几乎要重新定义setbuf()   任何目的和任何适合的方式   进入预定义的界面   setbuf()

答案 1 :(得分:4)

确定。缩回。

在过去几天完成文档和已经提出的提案之后,现在看来很明显这可能不起作用(因为它是实现定义的)。

正如您在上述说明中所述:

  

27.5.2.4.2:1效果:以本条款(27.8.1.4,27.9.1.5)中从basic_streambuf派生的每个类别单独定义的方式影响流缓冲。

setbuf()的效果实际上是由它与27.8.1.4 underflow()的交互定义的;

  

返回:如果输入序列具有可用的读取位置,则返回traits :: to_int_type(* gptr())。否则,返回traits :: eof()。 已初始化的基础缓冲区中的任何字符都被视为输入序列的一部分

另外,要从流中获取更多字符,您需要检查27.9.1.5 showmanyc()

  

如果可以确定可以从输入序列中读取更多字符,则实现可能会为此函数签名提供一个重写定义。

对于stringstream缓冲区来说意味着它不会得到任何东西,因为缓冲区已经拥有整个流。

所以虽然它是实现定义它是如何做到的 它仍然是如何做到的。