为什么std :: basic_ios重载一元逻辑否定运算符? [英] Why does std::basic_ios overload the unary logical negation operator?

查看:156
本文介绍了为什么std :: basic_ios重载一元逻辑否定运算符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++ IO流的基类 std :: basic_ios 定义 operator void *()返回!fail() operator!() >。这让我想知道为什么我们需要 operator!()。当然,!是也可以通过隐式调用 operator void *()并取消其结果。



我在这里缺少一些东西,或者是因为历史原因, std :: basic_ios :: operator!()定义?



A comp.lang.c ++。moderated 的问题也没有带来任何答案。

解决方案

使用旧(阅读: cfront 后不长)C ++编译器,编译器不能保证在需要时对对象隐式调用typecast操作符。如果 iostream 没有运算符!声明,那么你不能期望! cout 在所有情况下工作。



这也是为什么运算符的原因。 void *()重载,而不是 operator int operator bool 。 ( bool 甚至不存在作为它自己的类型在标准的那一点。)我记得我的教授告诉我 if(),在C ++中,期望一个 void * ,因为该类型可以作为一个超集类型相对于那些表达式结果类型传递给如果语句,但我没有发现这在任何地方拼写。



gcc 2,当大多数人不支持模板或异常,或者如果他们没有完全支持他们,所以元编程C ++与模板仍然是一个理论练习,你确保检查运算符新没有返回空指针。



这让我坚持几年。



Stroustrup的 C ++编程语言的一个有趣的摘录,第3版。 (1997),第276页:


类型依赖于 istream 启用诸如

 之类的语句的转换函数,而(cin>> x)cout< X; 

输入操作 cin >> x 返回 istream& 。该值隐式转换为表示 cin 状态的值。然后可以通过 while 来测试该值。但是,通常不是一个好主意,因为在转换过程中信息丢失,定义从一种类型到另一种类型的隐式转换。


在C ++中有很多,似乎是一个可爱或聪明的胜过一致。我不介意一点,如果C ++聪明地处理上面的循环为:

  while(! > x).fail())cout < X; 

因为这样,尽管更冗长和更多的标点符号,

...其实,想想它,我不喜欢那些结构。拼写出来:

  for(;;)
{cin>> X;
if(!cin)
break;
cout<< X;
}

为什么我更喜欢这个?因为这个版本使得它更清楚如何扩展代码,比如说,一次处理两次读取,而不是一个。例如,现有代码复制了一系列浮点值,我们希望您更改它,使其将浮点值对齐并写出,每行两个,因为我们现在使用复数。



但我离题。


The C++ IO streams' base class std::basic_ios defines operator void*() to return !fail() and operator!() to return fail(). That makes me wonder why we need the operator!() at all. Certainly, !is would also work by implicitly calling operator void*() and negating its result.

Am I missing something here or is it purely for historical reasons that std::basic_ios::operator!() is defined?

A question on comp.lang.c++.moderated didn't bring any answers either.

解决方案

With old (read: not long after cfront) C++ compilers, the compiler was not guaranteed to implicitly call typecast operators on objects when needed. If iostream didn't have an operator ! declared, then you couldn't expect !cout to work in all cases. C++89 (or whatever the pre-C++98 standard was called) simply left the area undefined.

This is also why operator void*() was overloaded, and not operator int or operator bool. (bool didn't even exist as its own type in the standard at that point.) I remember my professor telling me that if(), under the hood, expected a void* in C++, because that type could act as a "superset" type relative to those expression result types that would be passed to an if statement, but I have not found this spelled out anywhere.

This was around the time of gcc 2, when most folks didn't support templates or exceptions, or if they did, didn't fully support them, so metaprogramming C++ with templates was still a theoretical exercise and you made sure to check that operator new didn't return a null pointer.

This drove me nuts for several years.

An interesting excerpt from Stroustrup's The C++ Programming Language, 3rd ed. (1997), page 276:

The istream and ostream types rely on a conversion function to enable statements such as

while (cin >> x) cout << x;

The input operation cin>>x returns an istream&. That value is implicitly converted to a value indicating the state of cin. The value can then be tested by while. However, it is typically not a good idea to define an implicit conversion from one type to another in such a way that information is lost in the conversion.

There's a lot in C++ that seems to be a victory of cute or clever over consistent. I wouldn't mind one bit if C++ was smart enough to handle the above loop as:

while (!(cin >> x).fail()) cout << x;

because this, while more verbose and more punctuation, is clearer to a beginning programmer.

... Actually, come to think of it, I don't like either of those constructs. Spell it out:

for(;;)
{   cin >> x;
    if(!cin)
        break;
    cout << x;
}

Why do I like this better? Because this version makes it far clearer how to expandthe code to, say, handle two reads at a time instead of one. For example, "The existing code copies a sequence of float values. We want you to change it so it pairs up the float values and writes them out, two per line, because we're now using complex numbers."

But I digress.

这篇关于为什么std :: basic_ios重载一元逻辑否定运算符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆