重载运算符将函数指针作为参数,如何检索函数指针的参数

Kaz*_*oom 1 c++ operator-overloading

我有一个重载的运算符<<试图让它像这样工作

mystream<<hex<<10;
Run Code Online (Sandbox Code Playgroud)

我有重载的方法

mytream& operator<<(ios_base& (*m) ios_base&)
Run Code Online (Sandbox Code Playgroud)

只要遇到十六进制就会调用此方法,因为方法中传递的参数是类型与十六进制相同的函数指针,或者像dec,oct这样的其他输出操作符.

我有两个问题

1)如何检索十六进制将运行的参数,在此示例中为10

2)我怎么知道<<操作符被调用为十六进制而不是其他操纵符函数,如oct和dec

谢谢

Ste*_*sop 7

1)十六进制不对参数10进行<<操作.运算符从左到右关联,这意味着您的代码与以下内容相同:

(mystream<<hex)<<10;
Run Code Online (Sandbox Code Playgroud)

因此,您的重载必须返回一个对象,当10移入其中时,以十六进制打印(或者如果不打印,则在某处写入数据).正如大家所说,这是通过在流对象本身中保存标志然后返回来完成的*this.使用原因正是因为"10"尚未可用,因为<<还没有评估第二个.第一个<<操作员调用无法打印任何内容 - 它必须在第二个调用时准备好.

2)hex是一个函数.它可以与其他功能进行比较:

ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
    if (m == hex) {
    } else if (m == oct) {
    } else if (m == dec) {
    }
}
Run Code Online (Sandbox Code Playgroud)

除非您通常不想这样做,否则您需要默认行为,例如:

ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
    return m(s);
}
Run Code Online (Sandbox Code Playgroud)

(我可能错了,我从来没有看过实现,但一般的想法是操作符调用操纵器函数,操纵器(名称中的线索)操纵流).

std::hexstd::ios::hex在其参数上设置格式标志.然后在你的operator<<(int)覆盖中,如果你有一个,通过调用检查格式标志flags().

3)采用参数的机械手也是函数,但它们的返回类型是未指定的,这意味着它取决于实现.查看我的gcc iomanip标题,setw返回_Setw,setprecision返回_Setprecision等.Apache库的表现方式不同,更像是无法操纵器.您可以使用参数化操纵器进行的唯一操作是将它们应用于iostream operator<<,它们没有已定义的成员函数或自己的运算符.

所以就像hex,来处理setw你应该继承std::ios_base,依靠operator<<您的图书馆提供的实现,那么当你来格式化数据,检查自己的宽度,精度等,使用width(),precision()等等,功能上ios_base.

也就是说,如果由于一些奇怪的原因你需要拦截operator<<这些操纵器的标准,你可能会沿着这些方向一起躲避:

template <typename SManip>
mystream &operator<<(mystream &s, SManip m) {
    stringstream ss;
    // set the state of ss to match that of s
    ss.width(s.width());
    ss.precision(s.precision());
    // etc
    ss << m;
    // set the state of s to match that of ss
    s.width(ss.width());
    s.precision(ss.precision());
    // etc
    return s;
}
Run Code Online (Sandbox Code Playgroud)

不过,我确实认为这是一个小屋.你真的不应该干扰流操纵器,只需让你的基类完成工作并查找结果.