bitsetクラスを自作する
昨日勉強したbitsetクラスですが、題材としてとても面白そうだと思ったので自作してみることにしました。
テンプレートクラスとビット演算に慣れるという意味でもちょうど良いと思います。
#include <iostream> #include <string> using namespace std; template<unsigned long SIZE> class mybitset { public: mybitset () { m_bit = 0; } mybitset (unsigned long bit) { m_bit = bit; } mybitset<SIZE>& set () { m_bit = (1 << SIZE) - 1; return *this; } mybitset<SIZE>& set (size_t pos,int val=1) { if ( SIZE <= pos ) { err(); } if ( val ) { m_bit |= (1 << pos); } else { m_bit &= ~(1 << pos); } return *this; } mybitset<SIZE>& reset () { m_bit = 0; return *this; } mybitset<SIZE>& reset(size_t pos) { if ( SIZE <= pos ) { err(); } return set(pos,0); } mybitset<SIZE>& flip() { m_bit = ~m_bit; m_bit &= (1 << SIZE) - 1; return *this; } mybitset<SIZE>& flip(size_t pos) { if ( SIZE <= pos ) { err(); } set(pos,((*this)[pos] ? 0 : 1)); return *this; } bool test(size_t pos) const { if ( SIZE <= pos ) { err(); } return (m_bit & (1 << pos)) ? true : false; } bool operator[](size_t pos) const { return test(pos); } bool operator==(const mybitset<SIZE>& bs) const { return m_bit == bs.m_bit; } bool operator!=(const mybitset<SIZE>& bs) const { return m_bit != bs.m_bit; } mybitset<SIZE>& operator<<=(size_t shift) { m_bit <<= shift; m_bit &= (1 << SIZE) - 1; return *this; } mybitset<SIZE>& operator>>=(size_t shift) { m_bit >>= shift; m_bit &= (1 << SIZE) - 1; return *this; } mybitset<SIZE> operator<<(size_t shift) const { mybitset<SIZE> bs(m_bit); return bs <<= shift; } mybitset<SIZE> operator>>(size_t shift) const { mybitset<SIZE> bs(m_bit); return bs >>= shift; } mybitset<SIZE> operator~() const { mybitset<SIZE> bs(m_bit); return bs.flip(); } size_t count () const { size_t cnt = 0; for(int i=0;i<SIZE;++i ) { if ( m_bit & (1 << i) ) { ++cnt; } } return cnt; } string to_string() const { string str; str.reserve(SIZE+1); for(int i=1;i<=SIZE;++i ) { str.append( (m_bit & (1 << (SIZE-i))) ? "1" : "0" ); } return str; } unsigned long to_ulong () const { return m_bit; } bool any () const { return m_bit != 0; } bool none () const { return m_bit == 0; } unsigned long size () const { return SIZE; } private: unsigned long m_bit; void err () const { // 取り合えず例外吐いておく throw("error"); } }; int main () { mybitset<8> bs; cout << bs.size() << endl; bs.set( 1 ); bs.set( 2 ); // どれか一つでもビットが立っていたら if ( bs.any() ) { // 立っているビットを確認する if ( bs[0] ) { cout << "bs[0] = ON" << endl; } if ( bs[1] ) { cout << "bs[1] = ON" << endl; } if ( bs[2] ) { cout << "bs[2] = ON" << endl; } if ( bs[3] ) { cout << "bs[3] = ON" << endl; } // test関数と[]演算子のオーバーロードは同じ if ( bs.test(0) ) { cout << "bs[0] = ON" << endl; } if ( bs.test(1) ) { cout << "bs[1] = ON" << endl; } if ( bs.test(2) ) { cout << "bs[2] = ON" << endl; } if ( bs.test(3) ) { cout << "bs[3] = ON" << endl; } } // ビットを文字列に変換する cout << "to_string = " << bs.to_string() << endl; // ビットが立っている数を数える cout << "count = " << bs.count() << endl; // ビットを反転する bs.flip(); cout << "to_string = " << bs.to_string() << endl; // ビットを数値に変換する cout << "to_ulong = " << bs.to_ulong() << endl; // 1番目だけビットを反転する bs.flip(1); cout << "to_string = " << bs.to_string() << endl; // 4番目のビットだけを落とす bs.reset( 4 ); cout << "to_string = " << bs.to_string() << endl; // 2ビット左へずらす bs = bs << 2; cout << "to_string = " << bs.to_string() << endl; // 2ビット右へずらす bs >>= 2; cout << "to_string = " << bs.to_string() << endl; // 引数なしsetは全ビットを立てる bs.set(); cout << "to_string = " << bs.to_string() << endl; // 引数なしresetは全ビットを落とす bs.reset(); cout << "to_string = " << bs.to_string() << endl; // ビットが一つも立っていなかったら if ( bs.none() ) { cout << "all bit OFF" << endl; } return 0; }
$ main 8 bs[1] = ON bs[2] = ON bs[1] = ON bs[2] = ON to_string = 00000110 count = 2 to_string = 11111001 to_ulong = 249 to_string = 11111011 to_string = 11101011 to_string = 10101100 to_string = 00101011 to_string = 11111111 to_string = 00000000 all bit OFF
できました。
いくつかの演算子に関しては実装していません。
基本的なものに関しては大体実装できたと思います。
エラーの処理やテスト等はまだまだ適当なのでバグもあるかとは思いますが、とりあえずは満足ということで。