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

发布于 2024-07-28 22:12:28 字数 406 浏览 1 评论 0原文

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

mystream<<hex<<10;

我重载了方法,

mytream& operator<<(ios_base& (*m) ios_base&)

每当遇到十六进制时都会调用该方法,因为方法中传递的参数是与十六进制相同类型的函数指针或像其他一些输出操纵器(如 dec、oct)一样。

我有两个问题

1) 如何检索十六进制将要操作的参数,在本例中为 10

2) 我如何知道 << 正在为十六进制调用运算符,而不是为八进制和十进制等其他操纵器函数调用

谢谢

i have an overloaded operator << trying to make it work like this

mystream<<hex<<10;

i have overloaded method

mytream& operator<<(ios_base& (*m) ios_base&)

This gets called whenever hex is encountered cause the parameter passed in the method is a function pointer of type same as hex or like some other output manipulators like dec, oct.

i have two problems

1) how do i retrieve the parameter the hex would be operating on, in this example 10

2) how do i know that the << operator is being called for hex and not other manipulator function like oct and dec

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

紫轩蝶泪 2024-08-04 22:12:28

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

(mystream<<hex)<<10;

因此您的重载必须返回一个对象,当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) {
    }
}

除非你通常不想这样做,否则你想要默认行为,类似于:(

ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
    return m(s);
}

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

std::hex 在其参数上设置 std::ios::hex 格式标志。 然后在您的operator<<(int) 重写中,如果您有的话,请通过调用flags() 检查格式标志。

3)接受参数的操纵器也是函数,但它们的返回类型未指定,这意味着它取决于实现。 查看我的 gcc iomanip 标头,setw 返回 _Setwset precision 返回 _Set precision,等等。 Apache 库的做法不同,更像是无参数操纵器。 您可以使用参数化操纵器进行的唯一可移植的操作是将它们应用到带有 operator<< 的 iostream,它们没有定义自己的成员函数或运算符。

因此,就像hex一样,要处理setw,您应该从std::ios_base继承,依赖于operator<< code> 实现由您的库提供,然后当您格式化数据时,请使用 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;
}

不过,我确实认为这是一个bodge。 您实际上不应该干扰流操纵器,只需让您的基类完成工作并查找结果即可。

1) hex is not operating on the parameter 10. << operators associate left-to-right, which means your code is the same as:

(mystream<<hex)<<10;

So your overload has to return an object which, when 10 is shifted into it, prints in hex (or if not prints, writes data somewhere). As everyone says, this is done by saving flags in the stream object itself, then returning *this. The reason flags are used is precisely because the "10" is not available yet, since the second << has not been evaluated yet. The first << operator call cannot print anything - it just has to get ready for when the second one is called.

2) hex is a function. It can be compared with other functions:

ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
    if (m == hex) {
    } else if (m == oct) {
    } else if (m == dec) {
    }
}

Except you don't normally want to do that, you want the default behaviour, which is something like:

ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
    return m(s);
}

(I may be wrong on that, I've never looked at the implementation, but the general idea is that the operator calls the manipulator function, and the manipulator (the clue's in the name) manipulates the stream).

std::hex sets the std::ios::hex format flag on its parameter. Then in your operator<<(int) override, if you have one, check the format flags by calling flags().

3) Manipulators which take paramers are functions too, but their return types are unspecified, meaning it's up to the implementation. Looking at my gcc iomanip header, setw returns _Setw, setprecision returns _Setprecision, and so on. The Apache library does it differently, more like the no-args manipulators. The only thing you can portably do with parameterized manipulators is apply them to an iostream with operator<<, they have no defined member functions or operators of their own.

So just like hex, to handle setw you should inherit from std::ios_base, rely on the operator<< implementation provided by your library, then when you come to format your data, examine your own width, precision, etc, using the width(), precision(), etc, functions on ios_base.

That said, if for some bizarre reason you needed to intercept the standard operator<< for these manipulators, you could probably bodge something together, along these lines:

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;
}

I do consider this a bodge, though. You're not really supposed to interfere with stream manipulators, just let your base class do the work and look up the results.

淡墨 2024-08-04 22:12:28

当使用 hexoctdec 调用 operator<< 时,请在 中设置一个标志mystream 对象。 当使用数字调用 operator<< 时,检查是否设置了这些标志。 如果是这样,请将数字转换为十六进制/八进制/十进制并显示。

When operator<< gets called with hex or oct or dec, set a flag in your mystream object. When operator<< is called with a number, check to see if any of these flags are set. If so, convert the number to hex/octal/decimal and display it.

说好的呢 2024-08-04 22:12:28

在回答第二个问题时,参数 m 是指向操纵器函数的指针。 您可以检查它是否不为 null,然后调用该函数并传递 *this。 正如 Zifre 建议的那样,hex() 就像在传递的流对象中设置一个标志一样简单。 然后在处理整数时,检查流对象中的标志是否设置,并进行相应的输出。

这就是标准库实现其操纵器功能的方式。

In answer to your second question, the parameter m is a pointer to the manipulator function. You can check that it's not null, then call that function, passing *this. hex() is as simple as setting a flag in the passed stream object, as Zifre suggested. Then when processing the integer, check if the flag in the stream object is set, and output accordingly.

This is how the standard library implements its manipulator functions.

枯寂 2024-08-04 22:12:28

在您的示例中,十六进制对流进行操作(更改其状态),而不是对以下参数进行操作。 hex 与其他 << 没有任何概念或任何关系。 来电。

看看其他 io 操纵器是如何实现的将会对解决问题大有帮助。

In your example, hex operates on (changes the state of) the stream, not the following parameters. hex has no notion of, or any relation to other << calls.

Looking at how other io manipulators are implemented would go a long way to clearing things up.

差↓一点笑了 2024-08-04 22:12:28

您应该操作 ios_base::flags

http://www.cplusplus.com/reference /iostream/ios_base/flags/

这是标准十六进制的作用。

You should be manipulating ios_base::flags

http://www.cplusplus.com/reference/iostream/ios_base/flags/

which is what the standard hex does.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文