Vec2 クラスを作る（モダンな C++ クラスデザインのためのチュートリアル）

<a href="http://www.adventar.org/calendars/922" target="_blank">初心者 C++er Advent Calendar 2015</a> 5 日目の記事です。
C++ のクラスデザインの入門として、二次元ベクトルを表現するクラスの作り方を解説します。

# 0. はじめに

地図上に 2 匹の動物 cat と dog がいます。
この 2 匹がどこにいるのか位置（座標）を決めて、2 匹の間の距離を計算しましょう。

クラスを使って書くとこうなります。

```cpp
const Vec2 catPos(3.2, 5.4);
const Vec2 dogPos(4.0, 7.5);
std::cout << "cat: " << catPos << '\n';
std::cout << "dog: " << dogPos << '\n';
std::cout << "distance: " << catPos.distanceFrom(dogPos) << '\n';
```
```text:実行結果
cat: (3.2,5.4)
dog: (4,7.5)
distance: 2.24722
```

クラスを使わないで書くとこうなります。

```cpp
const double catPosX = 3.2, catPosY = 5.4;
const double dogPosX = 4.0, dogPosY = 7.5;
std::cout << "cat: (" << catPosX << ',' << catPosY << ")\n";
std::cout << "dog: (" << dogPosX << ',' << dogPosY << ")\n";
std::cout << "distance: " << std::sqrt((dogPosX-catPosX)*(dogPosX-catPosX) + (dogPosY-catPosY)*(dogPosY-catPosY)) << '\n';
```

```text:実行結果
cat: (3.2,5.4)
dog: (4,7.5)
distance: 2.24722
```

適切なクラスを設計すれば、見通しの良いプログラムで問題解決ができるようになります。
この記事では二次元ベクトルを表現するクラスを作りながら、モダンな C++ におけるクラス設計の基本を学びます。

# 1. 二次元ベクトル
二次元ベクトルは、2 つの成分（x 成分と y 成分）で表されるベクトルです。
例えば、2D アクションゲームのキャラクターが画面のどこにいるかといった「位置」や、ビリヤードの球がどの方向にどれぐらいの速さで移動しているのかという「速度」が二次元ベクトルで表現されます。
それぞれの成分は、キャラクターの位置の場合は x 座標と y 座標、ビリヤードの球の速度の場合は x 軸方向の速度、y 軸方向の速度を示します。

# 2. クラスの名前を決めよう
二次元ベクトル (2D-Vector) を扱うクラスなので、名前は `Vec2` としましょう。
`Vector2D` でも OK です。`V2` では省略しすぎて「バージョン 2」と紛らわしいので避けるべきです。`Vector` はベクトルの次元がわからないので好ましくありません。

今回は扱いませんが、三次元ベクトルクラスを `Vec3`, 四次元ベクトルクラスを `Vec4` と名付けることで一貫性を得られます。

# 3. class にすべきか struct にすべきか
`class` と `struct` は、クラスの外から **メンバ** にアクセスできるかを決める **アクセス制御** のデフォルトの設定が異なります。`class` はすべてのメンバがデフォルトで `private` であり、`struct` はすべてのメンバがデフォルトで `public` です。それ以外は基本的に同じで、**実行時の性能やコストに違いはありません**。この記事では両方をまとめて「クラス」といいます。

`Vec2` クラスの場合、クラスの外からのアクセスを制限する必要があるメンバ変数や関数はありません。したがって、デフォルトのアクセス制御が `public` である `struct` を使いましょう。

```cpp
struct Vec2
{
	double x;
	double y;
};
```

# 4. コンストラクタを作ろう
`Vec2 v(10, 20);` のように、2 つの成分の値から `Vec2` 型のオブジェクトを作れるようにします。
<a href="http://dev.activebasic.com/egtra/2015/12/02/845/" target="_blank">統一初期化構文</a> を用いれば、何もしなくても `Vec2 v{10, 20};` と書くことができますが、初期化の方法を複数用意したり、カスタマイズしたりしたい場合には **コンストラクタ** を使います。

まずは `x`, `y` 2 つの値から `Vec2` 型のオブジェクトを構築するコンストラクタを作りましょう。


```cpp
struct Vec2
{
	double x;
	double y;

	Vec2(double _x, double _y) // コンストラクタ
		: x(_x)
		, y(_y) {}
};
```

次に、`Vec2 v;` のように、初期値を与えない場合のための **デフォルトコンストラクタ** も作りましょう。
自分でコンストラクタを定義することもできますが、`= default` とすることで、コンパイラによる **デフォルトの初期化** を利用できます。このときメンバ変数 `x`, `y` は未初期化のままです。

```cpp
struct Vec2
{
	double x;
	double y;

	Vec2() = default; // デフォルトコンストラクタ

	Vec2(double _x, double _y)
		: x(_x)
		, y(_y) {}
};
```

`Vec2` のデフォルトコンストラクタでは、値の未初期化を避けるために各成分を 0 で初期化するのも良いアイデアです。

```cpp
	Vec2()
		: x(0.0)
		, y(0.0) {}
```

しかし、その分実行時にコストが発生することに注意してください。
例えば `std::vector<Vec2> v(1000);` のように Vec2 型のオブジェクトを大量に作成するコードで、すべての要素の成分を 0 で初期化する処理が必要になります。

この程度の処理であればコンパイラの最適化によって、無視できる程度のコストに抑えられるかもしれませんが、最大限の実行時性能を求めるプログラマからは不満が出る設計になってしまうでしょう。どちらを採用するかは目的に応じて判断しましょう。

# 5. メンバ関数を作ろう
ベクトルの長さを計算する関数を **フリー関数**（非メンバ関数）で定義すると次のようになります。

```cpp
double Length(const Vec2& v)
{
	return std::sqrt(v.x * v.x + v.y * v.y);
}

int main()
{
	Vec2 v(10, 20);

	std::cout << Length(v) << '\n';
}
```

一方、**メンバ関数** では、自身のオブジェクトを明示的に示さずに、メンバの名前をそのまま使えます。

```cpp
struct Vec2
{
	double x;
	double y;

	Vec2() = default;

	Vec2(double _x, double _y)
		: x(_x)
		, y(_y) {}

	double length()	// ベクトルの長さを計算するメンバ関数
	{
		return std::sqrt(x * x + y * y);
	}
};

int main()
{
	Vec2 v(10, 20);

	std::cout << v.length() << '\n';
}
```

メンバ関数が自身のクラスのメンバ変数を変更しない場合は、関数の引数の並びの後に `const` をつけます。const をつけることでメンバ関数は **const メンバ関数** になり、const オブジェクトに対しても実行できるようになります。

```cpp
struct Vec2
{
	double x;
	double y;

	Vec2() = default;

	Vec2(double _x, double _y)
		: x(_x)
		, y(_y) {}

	double length() const // ベクトルの長さを計算する const メンバ関数
	{
		return std::sqrt(x * x + y * y);
	}
};

int main()
{
	const Vec2 v(10, 20);

	std::cout << v.length() << '\n'; // length() が const メンバ関数でないとコンパイルエラー
}
```

練習のために、ベクトルの計算で役に立ちそうなメンバ関数をいくつか実装してみましょう。

```cpp
struct Vec2
{
	double x;
	double y;

	Vec2() = default;

	Vec2(double _x, double _y)
		: x(_x)
		, y(_y) {}

	double length() const
	{
		return std::sqrt(x * x + y * y);
	}
	
	double lengthSquare() const	// ベクトルの長さの二乗
	{
		return x * x + y * y;
	}
	
	double dot(const Vec2& other) const	// もう一方のベクトルとの内積
	{
		return x * other.x + y * other.y;
	}
	
	double distanceFrom(const Vec2& other) const	// もう一方のベクトルとの距離
	{
		return std::sqrt((other.x - x) * (other.x - x) + (other.y - y) * (other.y - y));
	}

	Vec2 normalized() const	// 正規化（長さを１にした）ベクトル
	{
		return{ x / length() , y / length() };
	}
	
	bool isZero() const	// ゼロベクトルであるか
	{
		return x == 0.0 && y == 0.0;
	}
};
```

# 6. 演算子をオーバーロードしよう
【Q】: 位置 `Vec2(10, 20)` にいる人が、毎秒 `Vec2(3, 2)` の速度で移動したとき、3 秒後にはどこにいるでしょう？

― こんな問題は次のような式で計算するのが簡単です。

```cpp
const Vec2 answer = Vec2(10, 20) + 3 * Vec2(3, 2);
```

自分で定義したクラスが `+` や `-` などの **演算子** を使えるようにするには、クラスのオブジェクトに対する演算子の使い方とその処理を定義する必要があります。これを **演算子のオーバーロード** といいます。

まずはじめに単純な `+` と `-` をオーバーロードしましょう。
基本的な文法はメンバ関数と同じです。
関数名の代わりに `operator ■()` とすることで、`Vec2` 型の値 `v` に対する演算子 `■v` を定義できます。

```cpp
struct Vec2
{
	double x;
	double y;

	Vec2() = default;

	Vec2(double _x, double _y)
		: x(_x)
		, y(_y) {}

	double length() const
	{
		return std::sqrt(x * x + y * y);
	}
	
	double lengthSquare() const
	{
		return x * x + y * y;
	}
	
	double dot(const Vec2& other) const
	{
		return x * other.x + y * other.y;
	}
	
	double distanceFrom(const Vec2& other) const
	{
		return std::sqrt((other.x - x) * (other.x - x) + (other.y - y) * (other.y - y));
	}

	Vec2 normalized() const
	{
		return{ x / length() , y / length() };
	}
	
	bool isZero() const
	{
		return x == 0.0 && y == 0.0;
	}

	Vec2 operator +() const	// 単項 +
	{
		return *this;
	}

	Vec2 operator -() const	// 単項 -
	{
		return{ -x, -y };
	}
};

int main()
{
	const Vec2 a(1, 2);

	const Vec2 b = +a; // (1, 2)

	const Vec2 c = -a; // (-1, -2)
}
```

`operator ■(other)` で、`Vec2` 型の値 `v` に対する演算 `v ■ other` を定義できます。

```cpp
struct Vec2
{
	double x;
	double y;

	Vec2() = default;

	Vec2(double _x, double _y)
		: x(_x)
		, y(_y) {}

	double length() const
	{
		return std::sqrt(x * x + y * y);
	}
	
	double lengthSquare() const
	{
		return x * x + y * y;
	}
	
	double dot(const Vec2& other) const
	{
		return x * other.x + y * other.y;
	}
	
	double distanceFrom(const Vec2& other) const
	{
		return std::sqrt((other.x - x) * (other.x - x) + (other.y - y) * (other.y - y));
	}

	Vec2 normalized() const
	{
		return{ x / length() , y / length() };
	}
	
	bool isZero() const
	{
		return x == 0.0 && y == 0.0;
	}

	Vec2 operator +() const
	{
		return *this;
	}

	Vec2 operator -() const
	{
		return{ -x, -y };
	}

	Vec2 operator +(const Vec2& other) const // 2項 +
	{
		return{ x + other.x, y + other.y };
	}

	Vec2 operator -(const Vec2& other) const // 2項 -
	{
		return{ x - other.x, y - other.y };
	}

	Vec2 operator *(double s) const // 2項 *
	{
		return{ x * s, y * s };
	}

	Vec2 operator /(double s) const // 2項 /
	{
		return{ x / s, y / s };
	}
};

int main()
{
	const Vec2 a(1, 2), b(2, 4);

	const Vec2 c = a + b; // (3, 6)

	const Vec2 d = a - b; // (-1, -2)

	const Vec2 e = a * 3; // (3, 6)

	const Vec2 f = b / 2; // (0.5, 1)
}
```

複合代入演算は自身のメンバ変数を変更するため、`const` をつけることはできません。

```cpp
struct Vec2
{
	double x;
	double y;

	Vec2() = default;

	Vec2(double _x, double _y)
		: x(_x)
		, y(_y) {}

	double length() const
	{
		return std::sqrt(x * x + y * y);
	}
	
	double lengthSquare() const
	{
		return x * x + y * y;
	}
	
	double dot(const Vec2& other) const
	{
		return x * other.x + y * other.y;
	}
	
	double distanceFrom(const Vec2& other) const
	{
		return std::sqrt((other.x - x) * (other.x - x) + (other.y - y) * (other.y - y));
	}

	Vec2 normalized() const
	{
		return{ x / length() , y / length() };
	}
	
	bool isZero() const
	{
		return x == 0.0 && y == 0.0;
	}

	Vec2 operator +() const
	{
		return *this;
	}

	Vec2 operator -() const
	{
		return{ -x, -y };
	}

	Vec2 operator +(const Vec2& other) const
	{
		return{ x + other.x, y + other.y };
	}

	Vec2 operator -(const Vec2& other) const
	{
		return{ x - other.x, y - other.y };
	}

	Vec2 operator *(double s) const
	{
		return{ x * s, y * s };
	}

	Vec2 operator /(double s) const
	{
		return{ x / s, y / s };
	}

	Vec2& operator +=(const Vec2& other) // 複合代入演算 +=
	{
		x += other.x;
		y += other.y;
		return *this;
	}

	Vec2& operator -=(const Vec2& other) // 複合代入演算 -=
	{
		x -= other.x;
		y -= other.y;
		return *this;
	}

	Vec2& operator *=(double s) // 複合代入演算 *=
	{
		x *= s;
		y *= s;
		return *this;
	}

	Vec2& operator /=(double s) // 複合代入演算 /=
	{
		x /= s;
		y /= s;
		return *this;
	}
};

int main()
{
	Vec2 a(10, 20);

	a += Vec2(1, 2); // (11, 22)

	a -= Vec2(1, 2); // (10, 20)

	a *= 4; // (40, 80)

	a /= 2; // (20, 40)
}
```

`Vec2` 型の値 `v` が後にくる演算 `other ■ v` は、フリー関数としてクラスの外で `operator ■(other, v)` のように定義します。
メンバ関数ではないので、`const` はつきません。

```cpp
struct Vec2
{
	double x;
	double y;

	Vec2() = default;

	Vec2(double _x, double _y)
		: x(_x)
		, y(_y) {}

	double length() const
	{
		return std::sqrt(x * x + y * y);
	}
	
	double lengthSquare() const
	{
		return x * x + y * y;
	}
	
	double dot(const Vec2& other) const
	{
		return x * other.x + y * other.y;
	}
	
	double distanceFrom(const Vec2& other) const
	{
		return std::sqrt((other.x - x) * (other.x - x) + (other.y - y) * (other.y - y));
	}

	Vec2 normalized() const
	{
		return{ x / length() , y / length() };
	}
	
	bool isZero() const
	{
		return x == 0.0 && y == 0.0;
	}

	Vec2 operator +() const
	{
		return *this;
	}

	Vec2 operator -() const
	{
		return{ -x, -y };
	}

	Vec2 operator +(const Vec2& other) const
	{
		return{ x + other.x, y + other.y };
	}

	Vec2 operator -(const Vec2& other) const
	{
		return{ x - other.x, y - other.y };
	}

	Vec2 operator *(double s) const
	{
		return{ x * s, y * s };
	}

	Vec2 operator /(double s) const
	{
		return{ x / s, y / s };
	}

	Vec2& operator +=(const Vec2& other)
	{
		x += other.x;
		y += other.y;
		return *this;
	}

	Vec2& operator -=(const Vec2& other)
	{
		x -= other.x;
		y -= other.y;
		return *this;
	}

	Vec2& operator *=(double s)
	{
		x *= s;
		y *= s;
		return *this;
	}

	Vec2& operator /=(double s)
	{
		x /= s;
		y /= s;
		return *this;
	}
};

inline Vec2 operator *(double s, const Vec2& v) // Vec2 が後にくる 2項 *
{
	return{ s*v.x, s*v.y };
}

int main()
{
	const Vec2 a(10, 20);

	const Vec2 b = 3 * a; // (30, 60)
}
```

# 7. 入出力演算子をオーバーロードしよう
`Vec2` の値を標準入力・標準出力するたびにこんなコードを書いていては手間がかかります。

```cpp
Vec2 v;
char c;
std::cin >> c >> v.x >> c >> v.y >> c; // (10,20) と入力すると

v *= 2;

std::cout << '(' << v.x << ',' << v.y << ')'; // (20,40) と出力される
```

入出力ストリームに対する `<<`, `>>` 演算子もオーバーロードしてしまいましょう。

```cpp
struct Vec2
{
	double x;
	double y;

	Vec2() = default;

	Vec2(double _x, double _y)
		: x(_x)
		, y(_y) {}

	double length() const
	{
		return std::sqrt(x * x + y * y);
	}
	
	double lengthSquare() const
	{
		return x * x + y * y;
	}
	
	double dot(const Vec2& other) const
	{
		return x * other.x + y * other.y;
	}
	
	double distanceFrom(const Vec2& other) const
	{
		return std::sqrt((other.x - x) * (other.x - x) + (other.y - y) * (other.y - y));
	}

	Vec2 normalized() const
	{
		return{ x / length() , y / length() };
	}
	
	bool isZero() const
	{
		return x == 0.0 && y == 0.0;
	}

	Vec2 operator +() const
	{
		return *this;
	}

	Vec2 operator -() const
	{
		return{ -x, -y };
	}

	Vec2 operator +(const Vec2& other) const
	{
		return{ x + other.x, y + other.y };
	}

	Vec2 operator -(const Vec2& other) const
	{
		return{ x - other.x, y - other.y };
	}

	Vec2 operator *(double s) const
	{
		return{ x * s, y * s };
	}

	Vec2 operator /(double s) const
	{
		return{ x / s, y / s };
	}

	Vec2& operator +=(const Vec2& other)
	{
		x += other.x;
		y += other.y;
		return *this;
	}

	Vec2& operator -=(const Vec2& other)
	{
		x -= other.x;
		y -= other.y;
		return *this;
	}

	Vec2& operator *=(double s)
	{
		x *= s;
		y *= s;
		return *this;
	}

	Vec2& operator /=(double s)
	{
		x /= s;
		y /= s;
		return *this;
	}
};

inline Vec2 operator *(double s, const Vec2& v)
{
	return{ s*v.x, s*v.y };
}

template <class Char> // 出力ストリーム
inline std::basic_ostream<Char>& operator <<(std::basic_ostream<Char>& os, const Vec2& v)
{
	return os << Char('(') << v.x << Char(',') << v.y << Char(')');
}

template <class Char> // 入力ストリーム
inline std::basic_istream<Char>& operator >>(std::basic_istream<Char>& is, Vec2& v)
{
	Char unused;
	return is >> unused >> v.x >> unused >> v.y >> unused;
}

int main()
{
	Vec2 v;

	std::cin >> v; // (10,20) と入力すると

	std::cout << 2 * v << '\n'; // (20,40) と出力される
}
```

サンプルコードでは示していませんが、`basic_ostream` と `basic_istream` に対する `<<`, `>>` 演算子をオーバーロードすることで、それらを継承する `fstream` や `stringstream` でも `Vec2` を扱えるようになりました。

# 8. Don't Repeat Yourself
クラスを見渡すと、何箇所か同じコードを書いている冗長な部分が見つかります。
プログラムのバグを減らすにはコードを短くすることが大切です。別のメンバ関数で置き換えられる部分がないか見直してみましょう。

```cpp
struct Vec2
{
	double x;
	double y;

	Vec2() = default;

	Vec2(double _x, double _y)
		: x(_x)
		, y(_y) {}

	double length() const
	{
		return std::sqrt(lengthSquare()); // std::sqrt(x * x + y * y)
	}
	
	double lengthSquare() const
	{
		return dot(*this); // x * x + y * y
	}
	
	double dot(const Vec2& other) const
	{
		return x * other.x + y * other.y;
	}
	
	double distanceFrom(const Vec2& other) const
	{
		return (other - *this).length(); //  std::sqrt((other.x - x) * (other.x - x) + (other.y - y) * (other.y - y));
	}

	Vec2 normalized() const
	{
		return *this / length(); // { x / length() , y / length() }
	}
	
	bool isZero() const
	{
		return x == 0.0 && y == 0.0;
	}

	Vec2 operator +() const
	{
		return *this;
	}

	Vec2 operator -() const
	{
		return{ -x, -y };
	}

	Vec2 operator +(const Vec2& other) const
	{
		return{ x + other.x, y + other.y };
	}

	Vec2 operator -(const Vec2& other) const
	{
		return{ x - other.x, y - other.y };
	}

	Vec2 operator *(double s) const
	{
		return{ x * s, y * s };
	}

	Vec2 operator /(double s) const
	{
		return{ x / s, y / s };
	}

	Vec2& operator +=(const Vec2& other)
	{
		x += other.x;
		y += other.y;
		return *this;
	}

	Vec2& operator -=(const Vec2& other)
	{
		x -= other.x;
		y -= other.y;
		return *this;
	}

	Vec2& operator *=(double s)
	{
		x *= s;
		y *= s;
		return *this;
	}

	Vec2& operator /=(double s)
	{
		x /= s;
		y /= s;
		return *this;
	}
};

inline Vec2 operator *(double s, const Vec2& v)
{
	return{ s*v.x, s*v.y };
}

template <class Char>
inline std::basic_ostream<Char>& operator <<(std::basic_ostream<Char>& os, const Vec2& v)
{
	return os << Char('(') << v.x << Char(',') << v.y << Char(')');
}

template <class Char>
inline std::basic_istream<Char>& operator >>(std::basic_istream<Char>& is, Vec2& v)
{
	Char unused;
	return is >> unused >> v.x >> unused >> v.y >> unused;
}
```

# 9. constexpr
最後の仕上げとして、メンバ関数を `constexpr` (コンスタント・エクスプレッション) にしましょう。
`constexpr` をつけた関数の処理は、もし可能であればコンパイルの時点で計算されるようになり、実行時の計算コストを減らせます。

`constexpr` によって

```cpp
std::cout << (Vec2(10, 20) + Vec2(5, 5)).lengthSquare();
```

といった計算はコンパイルの時点で

```cpp
std::cout << 850;
```

というコードになり、実行時に計算するコストはゼロになります。

メンバ関数を `constexpr` 修飾するには、その関数で使用する関数が全て `constexpr` である必要があるなど、<a href="http://cpprefjp.github.io/lang/cpp11/constexpr.html" target="_blank">いくつかの制約</a> があります。例えば、`Vec2::lengthSquare()` は `constexpr` にできますが、`Vec2::length()` は `constexpr` でない `std::sqrt()` を使うため `constexpr` にできません。

可能なメンバ関数すべてを `constexpr` にして、`Vec2` クラスを完成させましょう。

# 10. 完成

```cpp
struct Vec2
{
	double x;
	double y;

	Vec2() = default;

	constexpr Vec2(double _x, double _y)
		: x(_x)
		, y(_y) {}

	double length() const
	{
		return std::sqrt(lengthSquare());
	}
	
	constexpr double lengthSquare() const
	{
		return dot(*this);
	}
	
	constexpr double dot(const Vec2& other) const
	{
		return x * other.x + y * other.y;
	}
	
	double distanceFrom(const Vec2& other) const
	{
		return (other - *this).length();
	}

	Vec2 normalized() const
	{
		return *this / length();
	}
	
	constexpr bool isZero() const
	{
		return x == 0.0 && y == 0.0;
	}

	constexpr Vec2 operator +() const
	{
		return *this;
	}

	constexpr Vec2 operator -() const
	{
		return{ -x, -y };
	}

	constexpr Vec2 operator +(const Vec2& other) const
	{
		return{ x + other.x, y + other.y };
	}

	constexpr Vec2 operator -(const Vec2& other) const
	{
		return{ x - other.x, y - other.y };
	}

	constexpr Vec2 operator *(double s) const
	{
		return{ x * s, y * s };
	}

	constexpr Vec2 operator /(double s) const
	{
		return{ x / s, y / s };
	}

	Vec2& operator +=(const Vec2& other)
	{
		x += other.x;
		y += other.y;
		return *this;
	}

	Vec2& operator -=(const Vec2& other)
	{
		x -= other.x;
		y -= other.y;
		return *this;
	}

	Vec2& operator *=(double s)
	{
		x *= s;
		y *= s;
		return *this;
	}

	Vec2& operator /=(double s)
	{
		x /= s;
		y /= s;
		return *this;
	}
};

inline constexpr Vec2 operator *(double s, const Vec2& v)
{
	return{ s*v.x, s*v.y };
}

template <class Char>
inline std::basic_ostream<Char>& operator <<(std::basic_ostream<Char>& os, const Vec2& v)
{
	return os << Char('(') << v.x << Char(',') << v.y << Char(')');
}

template <class Char>
inline std::basic_istream<Char>& operator >>(std::basic_istream<Char>& is, Vec2& v)
{
	Char unused;
	return is >> unused >> v.x >> unused >> v.y >> unused;
}
```
<a href="https://paiza.io/projects/e/fARod12BEEQZym_DlQVgYw" target="_blank">▲ コードを編集して実行してみる</a>
上記の URL では、このコードを実際に編集して実行結果を確かめることができます。

***
この記事に登場する C++ コードはすべてパブリックドメインとします。