C++は演算子のオーバーロードによって、ユーザー定義型に演算子を持たせることができる。各演算子には関連性があり、ひとつ定義すれば他の演算子も同じように書ける。たとえば、operator<()
さえ定義すれば、operator>()
、operator<=()
, operator>=()
はoperator<()
から定義できる。Boost Operators Libraryは、このような関連演算子を自動的に定義する機構を提供する。
整数型をラップした型を作るためには、多くの演算子を定義する必要がある。
Boost.Operatorsによって関連演算子を自動定義することによって、これだけで整数型を定義することができる。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::operators<MyInt> {
int v;
public:
MyInt(int v) : v(v) {}
bool operator<(const MyInt& x) const { return v < x.v; }
bool operator==(const MyInt& x) const { return v == x.v; }
MyInt& operator+=(const MyInt& x) { v += x.v; return *this; }
MyInt& operator-=(const MyInt& x) { v -= x.v; return *this; }
MyInt& operator*=(const MyInt& x) { v *= x.v; return *this; }
MyInt& operator/=(const MyInt& x) { v /= x.v; return *this; }
MyInt& operator%=(const MyInt& x) { v %= x.v; return *this; }
MyInt& operator|=(const MyInt& x) { v |= x.v; return *this; }
MyInt& operator&=(const MyInt& x) { v &= x.v; return *this; }
MyInt& operator^=(const MyInt& x) { v ^= x.v; return *this; }
MyInt& operator++() { ++v; return *this; }
MyInt& operator--() { --v; return *this; }
};
int main()
{
// operator<()によって自動生成される演算子
{
const MyInt x = 3;
assert(x < MyInt(4));
assert(x > MyInt(2));
assert(x <= MyInt(3));
assert(x >= MyInt(3));
}
// operator==()によって自動生成される演算子
{
const MyInt x = 3;
assert(x == MyInt(3));
assert(x != MyInt(2));
}
// operator+=()によって自動生成される演算子
{
MyInt x = 3;
x += MyInt(2);
assert(x == MyInt(5));
const MyInt y = x + MyInt(4);
assert(y == MyInt(9));
}
// 以下略...
}
boost::operators
型をprivate
継承したクラスでは、
operator<()
を定義することによって、operator>()
、operator<=()
、operator>=()
が自動的に定義され、operator==()
を定義することによって、operator!=()
が定義され、operator+=
によってoperator+()
が定義され、他の関連演算子も同様に自動的に定義される。
大小比較の演算子、すなわち、operator<()
、operator>()
、operator<=()
、operator>=()
は、boost::less_than_comparable
をprivate
継承することにより、operator<()
だけを定義すれば、それ以外の関連演算子が自動的に定義される。
メンバ関数として定義する場合
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::less_than_comparable<MyInt> {
int v;
public:
MyInt(int v) : v(v) {}
bool operator<(const MyInt& x) const { return v < x.v; }
};
int main()
{
// operator<()によって自動生成される演算子
{
const MyInt x = 3;
assert(x < MyInt(4));
assert(x > MyInt(2));
assert(x <= MyInt(3));
assert(x >= MyInt(3));
}
}
非メンバ関数として定義する場合
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::less_than_comparable<MyInt, MyInt> {
int v;
public:
MyInt(int v) : v(v) {}
friend bool operator<(const MyInt& a, const MyInt& b)
{ return a.v < b.v; }
};
int main()
{
// operator<()によって自動生成される演算子
{
const MyInt x = 3;
assert(x < MyInt(4));
assert(x > MyInt(2));
assert(x <= MyInt(3));
assert(x >= MyInt(3));
}
}
等値比較の演算子、すなわち、operator==()
、operator!=()
は、boost::equality_comparable
をprivate
継承することにより、operator==()
だけを定義すれば、関連するoperator!=()
が自動的に定義される。
メンバ関数として定義する場合
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::equality_comparable<MyInt> {
int v;
public:
MyInt(int v) : v(v) {}
bool operator==(const MyInt& x) const
{ return v == x.v; }
};
int main()
{
// operator==()によって自動生成される演算子
{
const MyInt x = 3;
assert(x == MyInt(3));
assert(x != MyInt(2));
}
}
非メンバ関数として定義する場合
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::equality_comparable<MyInt, MyInt> {
int v;
public:
MyInt(int v) : v(v) {}
friend bool operator==(const MyInt& a, const MyInt& b)
{ return a.v == b.v; }
};
int main()
{
// operator==()によって自動生成される演算子
{
const MyInt x = 3;
assert(x == MyInt(3));
assert(x != MyInt(2));
}
}
加算演算子であるoperator+=()
、operator+()
は、boost::addable
をprivate
継承することにより、operator+=()
を定義するだけでoperator+()
が自動的に定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::addable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator+=(const MyInt& x)
{
v += x.v;
return *this;
}
};
int main()
{
// operator+=()によって自動生成される演算子
MyInt x = 3;
x += MyInt(2);
assert(x.v == 5);
const MyInt y = x + MyInt(4);
assert(y.v == 9);
}
減算演算子であるoperator-=()
、operator-()
は、boost::subtractable
をprivate
継承することにより、operator-=()
を定義するだけでoperator-()
が自動的に定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::subtractable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator-=(const MyInt& x)
{
v -= x.v;
return *this;
}
};
int main()
{
// operator-=()によって自動生成される演算子
MyInt x = 5;
x -= MyInt(2);
assert(x.v == 3);
const MyInt y = x - MyInt(1);
assert(y.v == 2);
}
乗算演算子であるoperator*=()
, operator*()
は、boost::multipliable
をprivate
継承することにより、operator*=()
定義するだけで、自動的にoperator*()
が定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::multipliable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator*=(const MyInt& x)
{
v *= x.v;
return *this;
}
};
int main()
{
// operator*=()によって自動生成される演算子
MyInt x = 5;
x *= MyInt(2);
assert(x.v == 10);
const MyInt y = x * MyInt(2);
assert(y.v == 20);
}
除算演算子であるoperator/=()
、operator/()
は、boost::dividable
をprivate
継承することにより、operator/=()
を定義するだけで、operator/()
が自動定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::dividable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator/=(const MyInt& x)
{
v /= x.v;
return *this;
}
};
int main()
{
// operator/=()によって自動生成される演算子
MyInt x = 20;
x /= MyInt(2);
assert(x.v == 10);
const MyInt y = x / MyInt(2);
assert(y.v == 5);
}
剰余演算子であるoperator%=()
、operator%()
は、boost::modable
をprivate
継承することにより、operator%=()
を定義するだけで、operator%()
が自動定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::modable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator%=(const MyInt& x)
{
v %= x.v;
return *this;
}
};
int main()
{
// operator%=()によって自動生成される演算子
MyInt x = 20;
x %= MyInt(2);
assert(x.v == 0);
const MyInt y = MyInt(7) % MyInt(2);
assert(y.v == 1);
}
OR演算子であるoperator|=()
、operator|()
は、boost::orable
をprivate
継承することにより、operator|=()
を定義するだけで、operator|()
が自動定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::orable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator|=(const MyInt& x)
{
v |= x.v;
return *this;
}
};
int main()
{
// operator|=()によって自動生成される演算子
MyInt x = 0x55;
x |= MyInt(0x0F);
assert(x.v == 0x5F);
const MyInt y = MyInt(0x55) | MyInt(0x0F);
assert(y.v == 0x5F);
}
AND演算子、operator&=()
、operator&()
は、boost::andable
をprivate
継承することにより、operator&=()
を定義するだけで、operator&()
が自動定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::andable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator&=(const MyInt& x)
{
v &= x.v;
return *this;
}
};
int main()
{
// operator&=()によって自動生成される演算子
MyInt x = 0x55;
x &= MyInt(0x0F);
assert(x.v == 0x05);
const MyInt y = MyInt(0x55) & MyInt(0x0F);
assert(y.v == 0x05);
}
XOR演算子であるoperator^=()
、operator^()
は、boost::xorable
をprivate
継承することにより、operator^=()
を定義するだけで、operator^()
が自動定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::xorable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator^=(const MyInt& x)
{
v ^= x.v;
return *this;
}
};
int main()
{
// operator^=()によって自動生成される演算子
MyInt x = 0x55;
x ^= MyInt(0x0F);
assert(x.v == 0x5A);
const MyInt y = MyInt(0x55) ^ MyInt(0x0F);
assert(y.v == 0x5A);
}
インクリメント演算子である前置++()
, 後置++()
は、boost::incrementable
をprivate
継承することにより、前置++()
を定義するだけで、後置++()
が自動定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::incrementable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator++()
{
++v;
return *this;
}
};
int main()
{
// operator++()によって自動生成される演算子
MyInt x = 1;
assert((++x).v == 2);
MyInt y = 1;
assert((y++).v == 1);
assert(y.v == 2);
}
デクリメント演算子である前置--()
、後置--()
は、boost::decrementable
をprivate
継承することにより、前置--()
を定義するだけで、後置--()
が自動定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::decrementable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator--()
{
--v;
return *this;
}
};
int main()
{
// operator--()によって自動生成される演算子
MyInt x = 2;
assert((--x).v == 1);
MyInt y = 2;
assert((y--).v == 2);
assert(y.v == 1);
}
左シフト演算子であるoperator<<=()
、operator<<()
は、boost::left_shiftable
をprivate
継承することにより、operator<<=()
を定義するだけで、operator<<()
が自動定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::left_shiftable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator<<=(MyInt x)
{
v <<= x.v;
return *this;
}
};
int main()
{
// operator<<=()によって自動生成される演算子
MyInt x = 100;
x <<= MyInt(1);
assert(x.v == 200);
MyInt y = 100;
y = y << MyInt(1);
assert(y.v == 200);
}
右シフト演算子であるoperator>>=()
、operator>>()
は、boost::right_shiftable
をprivate
継承することにより、operator>>=()
を定義するだけで、operator>>()
が自動定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::right_shiftable<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
MyInt& operator>>=(MyInt x)
{
v >>= x.v;
return *this;
}
};
int main()
{
// operator>>=()によって自動生成される演算子
MyInt x = 100;
x >>= MyInt(1);
assert(x.v == 50);
MyInt y = 100;
y = y >> MyInt(1);
assert(y.v == 50);
}
等値比較演算子であるoperator==()
は、小なり演算子operator<()
で定義することができる。
boost::equivalent
をprivate
継承することにより、operator<()
を定義するだけで、operator==()
が自動定義される。
#include <cassert>
#include <boost/operators.hpp>
class MyInt : private boost::equivalent<MyInt> {
public:
int v;
MyInt(int v) : v(v) {}
bool operator<(MyInt x) const
{
return v < x.v;
}
};
int main()
{
// operator<()によって自動生成される演算子
assert(MyInt(1) < MyInt(2));
assert(MyInt(2) == MyInt(2));
}