-
-
Save mattsan/f0795ab2c412ddf5d141be0d04948aa6 to your computer and use it in GitHub Desktop.
ビットを操作する道具を自分で作る
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// bits-step1.cpp | |
// | |
// compile | |
// $ g++ -o bits-step1 --std=c++11 bits-step1.cpp | |
// | |
// run | |
// $ ./bits-step1 | |
template<unsigned int N> class Bits { | |
public: | |
typedef Bits<N> TYPE; | |
static const unsigned int SIZE = N; | |
static const unsigned int MASK = (1u << SIZE) - 1u; | |
Bits(unsigned int value) : value_(value & MASK) {} | |
// unsigned int の値を代入できるようにするための代入演算子 | |
TYPE& operator = (unsigned int new_value) { | |
value_ = new_value & MASK; | |
return *this; | |
} | |
// unsigned int に変換できるようにするための型変換演算子 | |
operator unsigned int () const { return value_; } | |
private: | |
unsigned int value_; | |
}; | |
#include <iostream> | |
using namespace std; | |
int main(int, char* []) { | |
Bits<3> a(0x02); // 010 | |
Bits<5> b(0x03); // 0_0011 | |
Bits<8> c(0x04); // 0000_0100 | |
cout << hex; | |
cout << "a = " << a << "\n" // => 2 | |
<< "b = " << b << "\n" // => 3 | |
<< "c = " << c << "\n"; // => 4 | |
// 格納できるビット長より大きな値を代入する | |
a = 0x09; // 1001 | |
b = 0x21; // 10_0001 | |
c = 0x101; // 1_0000_0001 | |
cout << "a = " << a << "\n" // => 1 | |
<< "b = " << b << "\n" // => 1 | |
<< "c = " << c << "\n"; // => 1 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// bits-step2.cpp | |
// | |
// compile | |
// $ g++ -o bits-step2 --std=c++11 bits-step2.cpp | |
// | |
// run | |
// $ ./bits-step2 | |
template<unsigned int N> class Bits { | |
public: | |
typedef Bits<N> TYPE; | |
static const unsigned int SIZE = N; | |
static const unsigned int MASK = (1u << SIZE) - 1u; | |
Bits(unsigned int value) : value_(value & MASK) {} | |
// unsigned int の値を代入できるようにするための代入演算子 | |
TYPE& operator = (unsigned int new_value) { | |
value_ = new_value & MASK; | |
return *this; | |
} | |
// unsigned int に変換できるようにするための型変換演算子 | |
operator unsigned int () const { return value_; } | |
private: | |
unsigned int value_; | |
}; | |
template<unsigned int N, unsigned int M> class Composit { | |
public: | |
typedef Composit<N, M> TYPE; | |
typedef Bits<N> LEFT_TYPE; | |
typedef Bits<M> RIGHT_TYPE; | |
static const unsigned int SIZE = LEFT_TYPE::SIZE + RIGHT_TYPE::SIZE; | |
static const unsigned int MASK = (1u << SIZE) - 1u; | |
Composit(LEFT_TYPE& left, RIGHT_TYPE& right) : left_(left), right_(right) {} | |
// 型変換演算子 | |
operator unsigned int () const { | |
return ((static_cast<unsigned int>(left_) << RIGHT_TYPE::SIZE) | static_cast<unsigned int>(right_)) & MASK; | |
} | |
private: | |
LEFT_TYPE& left_; | |
RIGHT_TYPE& right_; | |
}; | |
template<unsigned int N, unsigned int M> Composit<N, M> combine(Bits<N>& left, Bits<M>& right) { | |
return Composit<N, M>(left, right); | |
} | |
#include <iostream> | |
using namespace std; | |
int main(int, char* []) { | |
Bits<3> a(0x02); // 010 | |
Bits<5> b(0x03); // 0_0011 | |
cout << hex; | |
cout << "a = " << a << "\n" // => 010 = 0x02 | |
<< "b = " << b << "\n" // => 0_0011 = 0x03 | |
<< "ab = " << combine(a, b) << "\n" // => 0100_0011 = 0x43 | |
<< "ba = " << combine(b, a) << "\n" // => 0001_1010 = 0x1a | |
<< "aa = " << combine(a, a) << "\n"; // => 01_0010 = 0x12 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// bits-step3.cpp | |
// | |
// compile | |
// $ g++ -o bits-step3 --std=c++11 bits-step3.cpp | |
// | |
// run | |
// $ ./bits-step3 | |
template<unsigned int N> class Bits { | |
public: | |
typedef Bits<N> TYPE; | |
static const unsigned int SIZE = N; | |
static const unsigned int MASK = (1u << SIZE) - 1u; | |
Bits(unsigned int value) : value_(value & MASK) {} | |
// unsigned int の値を代入できるようにするための代入演算子 | |
TYPE& operator = (unsigned int new_value) { | |
value_ = new_value & MASK; | |
return *this; | |
} | |
// unsigned int に変換できるようにするための型変換演算子 | |
operator unsigned int () const { return value_; } | |
private: | |
unsigned int value_; | |
}; | |
template<unsigned int N, unsigned int M> class Composit { | |
public: | |
typedef Composit<N, M> TYPE; | |
typedef Bits<N> LEFT_TYPE; | |
typedef Bits<M> RIGHT_TYPE; | |
static const unsigned int SIZE = LEFT_TYPE::SIZE + RIGHT_TYPE::SIZE; | |
static const unsigned int MASK = (1u << SIZE) - 1u; | |
Composit(LEFT_TYPE& left, RIGHT_TYPE& right) : left_(left), right_(right) {} | |
// 型変換演算子 | |
operator unsigned int () const { | |
return ((static_cast<unsigned int>(left_) << RIGHT_TYPE::SIZE) | static_cast<unsigned int>(right_)) & MASK; | |
} | |
// 代入演算子 | |
TYPE& operator = (unsigned int new_value) { | |
left_ = (new_value >> RIGHT_TYPE::SIZE) & LEFT_TYPE::MASK; | |
right_ = new_value & RIGHT_TYPE::MASK; | |
return *this; | |
} | |
private: | |
LEFT_TYPE& left_; | |
RIGHT_TYPE& right_; | |
}; | |
template<unsigned int N, unsigned int M> Composit<N, M> combine(Bits<N>& left, Bits<M>& right) { | |
return Composit<N, M>(left, right); | |
} | |
#include <iostream> | |
using namespace std; | |
int main(int, char* []) { | |
Bits<3> a(0); | |
Bits<5> b(0); | |
combine(a, b) = 0x3c; // 0011_1100 => 001, 1_1100 = 0x01, 0x1c | |
cout << hex | |
<< "a = " << a << "\n" // => 0x01 | |
<< "b = " << b << "\n"; // => 0x1c | |
combine(a, b) = combine(b, a); // 1_1100, 001 -> 1110_0001 -> 111, 0_0001 = 0x07, 0x01 | |
cout << hex | |
<< "a = " << a << "\n" // => 0x07 | |
<< "b = " << b << "\n"; // => 0x01 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// bits-step4.cpp | |
// | |
// compile | |
// $ g++ -o bits-step4 --std=c++11 bits-step4.cpp | |
// | |
// run | |
// $ ./bits-step4 | |
template<unsigned int N> class Bits { | |
public: | |
typedef Bits<N> TYPE; | |
static const unsigned int SIZE = N; | |
static const unsigned int MASK = (1u << SIZE) - 1u; | |
Bits(unsigned int value) : value_(value & MASK) {} | |
// unsigned int の値を代入できるようにするための代入演算子 | |
TYPE& operator = (unsigned int new_value) { | |
value_ = new_value & MASK; | |
return *this; | |
} | |
// unsigned int に変換できるようにするための型変換演算子 | |
operator unsigned int () const { return value_; } | |
private: | |
unsigned int value_; | |
}; | |
template<unsigned int N, unsigned int M> class Composit { | |
public: | |
typedef Composit<N, M> TYPE; | |
typedef Bits<N> LEFT_TYPE; | |
typedef Bits<M> RIGHT_TYPE; | |
static const unsigned int SIZE = LEFT_TYPE::SIZE + RIGHT_TYPE::SIZE; | |
static const unsigned int MASK = (1u << SIZE) - 1u; | |
Composit(LEFT_TYPE& left, RIGHT_TYPE& right) : left_(left), right_(right) {} | |
// 型変換演算子 | |
operator unsigned int () const { | |
return ((static_cast<unsigned int>(left_) << RIGHT_TYPE::SIZE) | static_cast<unsigned int>(right_)) & MASK; | |
} | |
// 代入演算子 | |
TYPE& operator = (unsigned int new_value) { | |
left_ = (new_value >> RIGHT_TYPE::SIZE) & LEFT_TYPE::MASK; | |
right_ = new_value & RIGHT_TYPE::MASK; | |
return *this; | |
} | |
private: | |
LEFT_TYPE& left_; | |
RIGHT_TYPE& right_; | |
}; | |
template<unsigned int N, unsigned int M> Composit<N, M> combine(Bits<N>& left, Bits<M>& right) { | |
return Composit<N, M>(left, right); | |
} | |
template<unsigned int N, unsigned int M> Composit<N, M> operator , (Bits<N>& left, Bits<M>& right) { | |
return combine(left, right); | |
} | |
#include <iostream> | |
using namespace std; | |
int main(int, char* []) { | |
Bits<3> a(0); | |
Bits<5> b(0); | |
(a, b) = 0x3c; // 0011_1100 => 001, 1_1100 = 0x01, 0x1c | |
cout << hex | |
<< "a = " << a << "\n" // => 0x01 | |
<< "b = " << b << "\n"; // => 0x1c | |
(a, b) = (b, a); // 1_1100, 001 -> 1110_0001 -> 111, 0_0001 = 0x07, 0x01 | |
cout << hex | |
<< "a = " << a << "\n" // => 0x07 | |
<< "b = " << b << "\n"; // => 0x01 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment