まずは自らのツイートの引用から。
operator , (コンマ演算子)のオーバーロードが…、わたしをC++のダークサイドへといざなう…。…ちょっとダークサイドをのぞいてきます…。
「見よダークサイド見よダークサイド 今キミ待つ闇からの/あのダークサイドあのダークサイドが 誘う闇の奥へ」http://bit.ly/aKGAks
というわけで。ダークサイドから帰還しました(=_=)ゝ:ビットをもっと自由自在に扱えるようにしてみた。 http://d.hatena.ne.jp/E_Mattsan/20100308/1268052182
よっふぃ〜さんがブログで言及して*1くださったように、このビット操作は実際の利用を考えた場合、使う人を惑わす危ういやり方なんですよね。
実のところ見た目の変態度だけでなく、予想外の振る舞いをしかねないので注意が必要です。
たとえばこんなコード。12ビットの数値のうち中央の4ビットをシフトしたい、という場合。
#include <iostream> #include "Bits.h" using namespace emattsan::bits; int main(int, char* []) { Signed<4> a, b, c; int n = 0x123; std::cout << std::hex; std::cout << "before:" << n << std::endl; (a, b, c) = n; std::cout << "a:b:c = " << a << ":" << b << ":" << c << std::endl; std::cout << "a:b << 2:c = " << a << ":" << (b << 2) << ":" << c << std::endl; n = (a, b << 2, c); std::cout << "after:" << n << std::endl; return 0; }
これを実行すると、最初の3つの出力は次のようになります。
before:123 a:b:c = 1:2:3 a:b << 2:c = 1:8:3
なので、最後の出力は「183」と出てほしい気もしますが、現時点のコードでは実際はこうなります。
after:3
これは。Signed
にはoperator <<
が定義されていないので、オーバーロードされている型変換演算子によって組み込みの整数型に変換されてoperator <<
が適用されます。
そうすると(a, b << 2, c)
は、型で見ると(Signed<4>, long, Signed<4>)
という式になります。operator , (Signed<4>, long)
やoperator, (long, Signed<4>)
という演算子は定義されていませんから、本来のoperator ,
が機能します。結果、a
の値が評価されて値は捨てられ、次にb << 2
が評価されて値は捨てられ、最後にc
が評価され値がn
に代入されます。
これらを個人的には「C++のダークサイド」と呼んでいます。その力は強力なんですが、作り方使い方を間違えると収拾のつかないカオスな状況を生んでしまいます。
はてさて。当プログラムは、ダークサイドから力を持ち帰るのか、それとも混沌と化し闇に還るのか。自分の技術力の挑戦でもあります。