Skip to content

Instantly share code, notes, and snippets.

@mattsan
Created March 7, 2023 04:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattsan/f0795ab2c412ddf5d141be0d04948aa6 to your computer and use it in GitHub Desktop.
Save mattsan/f0795ab2c412ddf5d141be0d04948aa6 to your computer and use it in GitHub Desktop.
ビットを操作する道具を自分で作る
// 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
}
// 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
}
// 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
}
// 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