char
といえば、もっぱら文字を表すのに使われる型で、std::cout
はそれを前提とした動作をする。
具体的には…
char c = 65 // 文字コードがASCIIなら'A'と同じ
std::cout << c << std::endl
出力
A
#流れに逆らう
では、もしc
を文字ではなく数字として出力したい場合はどうするか。
ググってみるとStack Overflowにこんなのが。
http://stackoverflow.com/questions/14644716/how-to-output-a-character-as-an-integer-through-cout
投票数の多い回答を見ると、単項演算子+
をc
に付けるだけでよいという。
つまり、
char c = 65 // 文字コードがASCIIなら'A'と同じ
std::cout << +c << std::endl
出力
65
仕組みはよくわからないが、元のページによれば「数字として表示される型に昇格される」らしい。
つまりはint
とかにキャストするのと同じなのだろうか。
#動機
自分はchar
そのものに興味はないのだが、int8_t
・uint8_t
は処理系によってはsigned char
・unsigned char
をtypedefすることで実装されている。
typedefされた型はテンプレート特殊化では元の型と同じ扱いなので、単なる数値型としてint8_t
を使ってもchar
向けの特殊化の影響を受けてしまう。
これを回避する方策を探していたのだった。
(噂に聞く「強いtypedef」とかいうのがあればこういう問題もなくなるのだろうか…)
(2021/2/8追記)原理
約5年経ち「C++完全に理解した」ので原理について調べてみる。
C++ドラフトの[expr.unary.op]の単項+演算子の項には以下のような記載がある。
Integral promotion is performed on integral [...] operands.
The type of the result is the type of the promoted operand.
つまり、単項+演算子のオペランドには"integral promotion"なるものが働き、戻り値はその結果の型になるらしい。
"integral promotion"については[conv.prom]に以下のような記載がある。
A prvalue of an integer type [...] can be converted to a prvalue of type int
略した部分を含めて大雑把に言えば「intよりも小さい数値型のprvalueはint型のprvalueに変換できる」ということだ。
だが一点問題がある。変数は確かlvalueとかそのへんのやつで、少なくともprvalueではないはずだ。
これに関しては"lvalue-to-rvalue conversion"というのがあるらしい。([conv.lval])
A glvalue [...] can be converted to a prvalue.
この記事によると、glvalueはlvalueとその他の概念の総称らしいので、変数には適用できそうだ。
この2つの変換が合わさって、表題のような効果が得られるのだろう。