2016-04-25 13 views
11

このコードは、それが行うことになっているもの行いません。なぜstd::(i)ostreamはsigned/unsigned charをテキストではなく整数として扱うのですか?

#include <iostream> 
#include <cstdint> 

int main() 
{ 
    uint8_t small_integer; 
    std::cin >> small_integer; 
    std::cout << small_integer; 
} 

理由は単純です:uint8_tunsigned charのtypedefで、ストリームがテキストとして、このタイプの治療:
のVisual C++ 2015の実装

template<class _Traits> inline 
    basic_istream<char, _Traits>& operator>>(
     basic_istream<char, _Traits>& _Istr, unsigned char& _Ch) 
    { // extract an unsigned char 
    return (_Istr >> (char&)_Ch); 
    } 

の場合はoperator <<にキャストされた同様のコードです。

私の質問:

  1. は標準で必要とされる(ストリーミング演算子は、文字型ではなく整数として署名/ unsigned char型の治療)この振る舞いですか? そうである場合:
    1. 逆説的なセマンティクスの背後にある根拠はなんですか?
    2. これは欠陥と見なされるべきですが、このセマンティクスを変更する提案はありましたか?

私はおそらく、私はそれが直感に反する考える理由を少し説明を追加する必要があります。 型名にcharという文字が含まれていますが、signedまたはunsigned部分は特定の整数意味を指定します。これらの型は通常、バイトサイズの整数として使用されます。標準でさえ、int8_t/uint8_tと定義されています。

UPD:質問は、unsigned charsigned charのストリーミングオペレータオーバーロードの動作についてです。

+1

迷惑です。私は文字をcharとして扱いながら整数としてint8_tを扱う独自のto_string関数を使用しました。 uint8_t、int8_t、charについては、3つの異なる型にならないように完全に有効であると仮定しているので、別の特殊化を追加しました。 – Matt

+4

あなたの質問には答えられませんが、['std :: byte'](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0257r0.pdf)はこの問題を克服する。 – Praetorian

+0

@Praetorian、これは確かに興味深い提案ですが、それはまったく別の問題に取り組んでいます。 –

答えて

3

標準(n3797)は、次の言葉:

27.7.2.2.3 basic_istream ::演算子>>

template<class charT, class traits> 
basic_istream<charT,traits>& operator>>(basic_istream<charT,traits>& in, charT& c); 

template<class traits> 
basic_istream<char,traits>& operator>>(basic_istream<char,traits>& in, unsigned char& c); 

template<class traits> 
basic_istream<char,traits>& operator>>(basic_istream<char,traits>& in, signed char& c); 

12 EのFFのECTSは:フォーマットされたと同じように動作します(27.7.2.2.1で説明した)イントリオブジェクトが構築された後、から文字が抽出される in、if利用可能であり、c。それ以外の場合、関数はin.setstate(failbit)を呼び出します。

27.7.3.6.4文字挿入機能テンプレート

// specialization 
template<class traits> 
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, char c); 

// signed and unsigned 
template<class traits> 
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, signed char c); 

template<class traits> 
basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>& out, unsigned char c); 

1のE FFのクトは:うちのフォーマットされた出力機能(27.7.3.6.1)として振る舞います。文字シーケンスseqを構築します。 cがchar型で、ストリームの文字型がcharでない場合、seqはout.widen(c)で構成されます。それ以外の場合、seqはcで構成されます。 27.7.3.6.1で説明したseqのためのパディングを決定します。 seqを挿入します。 os.width(0)を呼び出します。

だから最初の質問への答え:はい、標準は operator >>operator <<が正確に動作 charunsigned charsigned charで同じことが必要ですが、それは彼らが単一の文字ではなく、整数を読み取り/書き込みです。残念ながら、標準ではなぜその理由が説明されていません。私は誰かが2と3

1
  1. に光を当てることを願っています標準で必要とされるこの振る舞いですか?そうであれば:

あなたはすでにこれに答えています。はい。標準では、iostreamが署名付きおよび非署名型のcharを処理する方法を定義しています。

  1. このような反直観的セマンティクスの背景には何がありますか?

signed charunsigned char文字種あるので、彼らは常に、入出力ストリームクラスによって文字として扱われるため。

手がかりは名前にあります:signed charは符号付き文字タイプです。 unsigned charは、符号なしの文字型です。他の整数型は、名前にintという名前が付いています(オプションの場合もありますが、たとえばshortおよびlong unsignedはそれぞれshort intおよびlong unsigned intと同じです)。

というのはなぜですか?はこれが正しいとは言えません。なぜなら、これはCやC++の歴史に関する設計書や理論的根拠ではないからです。

8ビットの整数のように動作するタイプを作成する場合は、(列挙型や値を保持する構造体を使用して)独自のオペレーションオーバーロードを定義する必要があります。

  1. これは欠陥とみなされるべきですか、このセマンティクスを変更する提案はありましたか?

いいえ、私はそうは思わない。彼らはいつもキャラクタ型であり、それを変更するにはあまりにも多くのコードを破るでしょう。

関連する問題