web-dev-qa-db-ja.com

std :: cinはどのようにしてブール値とそれ自体を同時に返すことができますか?

>>演算子を使用すると、演算子の左側にあるオブジェクトが返されるというC++の本を読んでいるので、この例では

std::cin >> value1;

コードはstd::cinを返します。

しかし、私がこれを行う場合

while(std::cin >> value1)

私のコードはstd::cinエラーが発生するまでループになります。つまり、演算子はstd::cinが失敗しない場合はtrue、std::cinの場合はfalseを返すboolを返す必要があります。 ] _失敗します。

どれですか?

32
gigi

[...]つまり、演算子がブール値を返すことを意味する必要があります[...]

いいえ、_std::cin_(参照による)を返します。 while(std::cin >> value);が機能する理由は、_std::istream_(_std::cin_のタイプ)に 変換演算子

変換演算子は基本的に、クラスを暗黙的に(explicitとマークされていない場合)特定の型に変換することを許可します。この場合、_std::istream_はその_operator bool_を定義して、エラー(通常はfailbit)が発生したかどうかを返します。

[std::ios_base::operator bool()]

ストリームにエラーがなく、I/O操作の準備ができている場合は、trueを返します。具体的には、!fail()を返します。


_explicit operator bool() const;
_

演算子がexplicitif (std::cin);のような暗黙の変換を許可しない)であっても、boolを必要とするコンテキストで使用される場合、修飾子は無視されることに注意してください。 ifwhileループ、forループのように。ただし、これらは例外であり、規則ではありません。

次に例を示します。

_if (std::cin >> value);  //OK, a 'std::istream' can be converted into a 'bool', which 
                         //therefore happens implicitly, without the need to cast it: 

if (static_cast<bool>(std::cin >> value)); //Unnecessary

bool b = std::cin >> value;  //Error!! 'operator bool' is marked explicit (see above), so 
                             //we have to call it explicitly:

bool b = static_cast<bool>(std::cin >> value); //OK, 'operator bool' is called explicitly
_
48
Rakete1111

_std::istream_(_std::cin_がオブジェクトであるクラス)には、次のメンバー関数があります。

_explicit operator bool() const;
_

オブジェクトがエラー状態の場合はfalseを返し、それ以外の場合はtrueを返します。これが、while(std::cin >> value1)コンストラクトが機能する理由です。 C++ 11より前は、代わりに次の非明示的な関数がありました。

_operator void*() const;
_

オブジェクトがエラー状態の場合、これはnullポインターを返し、同じ目的を果たします。

21

ストリームの操作はストリームへの参照を返します。

したがって、boolではありません。

これを行うことができるのと同じ理由で、結果をif条件に貼り付けることができます。

_void* ptr = foo();
if (ptr) { /*...*/ }
_

そして、そのことについては、これは:

_int x = foo();
if (x) { /*...*/ }
_

ここでのptrxはどちらも、条件で使用するためにbool変換できます。 _std::cin_の場合、変換は、この正確なタスクのために明示的に(しゃれを意図して)追加された_std::ostream_クラス内のoperator bool()によって行われます。

_std::cin_はタイプ_std::istream_です(これは _std::basic_istream<char>_typedefです)

異なるオーバーロードされた_operator>>_ for _basic_istream_ が表示された場合、それらはすべて_basic_istream_への参照を返しています。したがって、ここでの_operator>>_はboolを返さず、代わりに「_std::cin_」自体を返すことが1つ明確になります。 bool値を返す_operator>>_は表示されません。

では、問題は、_std::basic_istream_をboolにどのように変換するかということです。
答えは次のとおりです。変換演算子がこの目的で呼び出されています。

_std::basic_istream_は親から operator bool() を継承します_std::basic_ios_

_explicit operator bool() const;
_

これにより、_std::basic_istream_オブジェクトをboolに変換できます。 explicitとマークされているのは簡単に不思議に思うかもしれませんが( なぜexplicitとマークされているのか を参照)、それでもboolまたはifで暗黙的にwhileに変換されます。

この質問への答えは、ifまたはwhileが「暗黙的に」明示的な変換を使用することです。 ( @R。MartinhoFernandesによるこの回答 を参照)。したがって、ifwhile、およびforは、この「contexual変換」からboolへの暗黙的な変換が行われる場所の1つです。

1
Muhammad Ahmad