6

这是针对学校的练习,因此请仅提供提示,不要提供完整示例;-)

我有自己的机械手:

template<typename T, typename Tr=char_traits<T> >
ios_base& toggle(basic_ios<T,Tr>& io)
{
    if(io.flags() & ios::scientific)
    { io.unsetf(ios::scientific); io.flags(ios::fixed); }
    else { io.unsetf(ios::fixed); io.flags(ios::scientific); }
    return io;
 }

我写了这个,因为我必须用表单编写一个操纵器ios_base& my_manip(basic_ios&)

如果我这样使用它(不使用返回值):

toggle(cout);

...效果很好。但如果我这样使用它:

toggle(cout) << 54444.6456555 << endl;

这不起作用(因为 std::ios_base 没有 operator<<() 如下所述)。

一般来说,我没有得到什么ios_base& my_manip(basic_ios&)有用的……你有提示/例子吗?


你们已经帮了我很多了!我仍然不明白的是,通过 abasic_ios并回馈的动机ios_base(因为建议在我必须解决的练习中这样做......)。使用它的可能场景是什么???

4

2 回答 2

4

操纵器的问题在于它返回一个std::ios_base&而不是std::ostream&你可以写入的一个。您可以更改操纵器以采用std::ostream&as 参数并返回收到的引用。然而,输出流类定义了输出操作符,它接受指向函数的指针:

std::ostream& std::ostream::operator<< (std::ios_base& (*)(std::ios_base&)) { ... }

也就是说,您几乎可以按照自己的方式插入操纵器,例如std::hex

std::cout << std::hex << 123 << ' ' << std::dec << 123 << '\n';
于 2013-12-30T15:55:43.657 回答
2

除了 Dietmar 解决的问题之外:io.flags() & ios::scientific不返回 a bool,并且转换为bool可能不符合您的要求。你需要一些类似的东西:

if ( (io.flags() & ios::floatfield) == ios::fixed ) {
    io.setf( ios::scientific, ios::floatfield );
} else if ( (io.flags() & ios::floatfield) == ios::scientific ) {
    io.setf( ios::fixed, ios::floatfield );
} else {
    //  Whatever you want to happen first time around...
}

尽管是类型为 的变量的一部分...flagsfloatfield但它不是一个标志,而是一个至少可以取三个值的字段:fixedscientific它的默认值,这两个值都没有设置。(basefield并且 adjustfield行为相似。)

还要注意 ; 的两个参数形式的使用ios::setf。它专为这些位域格式参数而设计,并在设置第一个参数之前重置其第二个参数中的位。

我可能会补充一点,您可能不想调用io.flags 您的操纵器;这会将所有格式化标志设置为您提供的值,从而有效地重置所有其他格式化标志。如果您只输出浮点数,这可能不是问题(尽管showpos, showpoint,uppercase可能unitbuf是相关的),但您永远不会知道。

于 2013-12-30T16:56:57.163 回答