9

std :: wsマニピュレータを使用してストリームから抽出すると、失敗ビットが発生する必要がありますか?次のコードでは、Clangでコンパイルされた(Xcode 4.5.1内の)プログラムが最終アサーションに失敗します。明らかs >> std::wsにEOFで失敗を引き起こします。それでも、GCC4.7.2はアサーションに合格します。どちらが正しい?

#include <iostream>
#include <sstream>
#include <cassert>

int main(int argc, const char * argv[])
{
    {
        // Read string with trailing ws.
        std::istringstream s( "test   " );
        std::string test;

        s >> std::ws;
        assert( !s.fail() );    // No ws to skip, but no failure.

        s >> test;
        assert( test == "test" );
        assert( !s.fail() );

        s >> std::ws;
        assert( !s.fail() );    // No prob skipping trailing ws.
    }
    {
        // Retry with no trailing ws.
        std::istringstream s( "test" );
        std::string test;

        s >> std::ws;
        assert( !s.fail() );    // No ws to skip, but no failure.

        s >> test;
        assert( test == "test" );
        assert( !s.fail() );

        s >> std::ws;
        assert( !s.fail() );    // CLANG: Skipping absent ws at eof raises failbit.
    }

    return 0;
}
4

2 に答える 2

4

libc++が標準を正しく実装していると思います。

[ドラフトC++11標準であるN3290から引用しています。C++14はこれを変更しません。]

ws[istream.manip]で説明されており、次のように述べられています。

効果:フォーマットされていない入力関数として動作します(27.7.2.3、段落1で説明)。ただし、抽出された文字数はカウントされず、is.gcount()への後続の呼び出しによって返される値には影響しません。歩哨オブジェクトを作成した後、次に使用可能な文字cが空白である限り、またはシーケンスに文字がなくなるまで、文字を抽出します。空白文字は、sentry :: centry(27.7.2.1.3)で使用されるのと同じ基準で区別されます。使用可能なものがなくなったためにwsが文字の抽出を停止した場合、eofbitは設定されますが、失敗ビットは設定されません。

正しい動作を決定するためのここでのキーフレーズは、「歩哨オブジェクトを構築した後」です。

セントリーオブジェクトは[istream::sentry]で説明されており、そこからテキストが始まります。

1クラス歩哨は、例外安全なプレフィックスおよびサフィックス操作を実行する責任があるクラスを定義します。

明示的な歩哨(basic_istream&is、bool noskipws = false);

2効果:is.good()がfalseの場合、is.setstate(failbit)を呼び出します。それ以外の場合は、フォーマット済みまたはフォーマットされていない入力の準備をします。...など..。

これが利用可能な唯一の歩哨コンストラクターであるため、libc++が使用するコンストラクターです。

したがって、文字を抽出する前に失敗ビットが設定されるため、段落の最後のテキストは適用されません。ストリームに含まれている場合" "(つまり、最後に単一のスペースがある場合)、呼び出しstd::wsは失敗ビットを設定せず、eof(OPが発生すると予想されるもの)だけを設定します。

于 2014-04-21T16:24:23.540 に答える
3

C ++ 11、§27.7.2.4/ 1:

ws使用可能なものがなくなったために文字の抽出を停止した場合は、を設定しますが、は設定eofbitしませんfailbit

そのため、マニピュレータは直接ws設定されません。failbitただし、Marshall Clowが彼の回答で指摘しているように、そうする必要はありません。歩哨オブジェクトを作成する必要があり、歩哨オブジェクトは、の場合にフェイルビットを設定する必要があります!stream.good()

于 2012-11-16T20:18:05.260 に答える