2018年01月30日
《その265》 問題演習 p.349演習9-8 (2)
新版明解C++中級編 p.349 演習9-8
(1)〜(3)の各クラステンプレートをインクルードモデルで実現したプログラム を作成せよ。
(2)クラステンプレート Array<bool>
// Array.h
#ifndef ___ClassTemplateArray
#define ___ClassTemplateArray
template <class Type> class Array { };
#endif
// BoolArray.h
#ifndef ___ClassTemplateBoolArray
#define ___ClassTemplateBoolArray
#include <limits>
#include "Array.h"
template<> class Array<bool> {
typedef unsigned char BYTE;
static const int CHAR_BITS
= std::numeric_limits<unsigned char>::digits;
// bool型配列の要素数
int nelem;
// bool型配列を格納するためのBYTE型配列の要素数
int velem;
// BYTE型先頭要素へのポインタ
BYTE* vec;
// バイト型配列要素の必要数を算出
static int size_of(int sz) {
return (sz + CHAR_BITS - 1) / CHAR_BITS;
}
public:
// 該当バイト中の該当ビットへの参照を表すクラス
class BitOfByteRef {
BYTE& vec; // 参照先BYTE
int idx; // 参照先BYTE中のビット番号
public:
// コンストラクタ
BitOfByteRef(BYTE& r, int i)
: vec(r), idx(i) { }
// 該当ビットを bool型で返却
operator bool() const { return (vec >> idx) & 1U; }
// 該当ビットに true または false をセット
BitOfByteRef& operator=(bool b) {
if (b)
vec |= 1U << idx;
else
vec &= ~(1U << idx);
return *this;
}
};
// 添字範囲エラー
class IdxRngErr {
const Array* ident;
int index;
public:
IdxRngErr(const Array* p, int i) : ident(p), index(i) { }
int Index() const { return index; }
};
// コンストラクタ
explicit Array(int sz, bool v = bool())
: nelem(sz), velem(size_of(sz)) {
vec = new BYTE[velem];
// 全要素を初期化
for (int i = 0; i < velem; i++)
vec[i] = v;
}
// コピーコンストラクタ
Array(const Array& x) {
if (&x == this) {
nelem = 0;
vec = NULL;
}
else {
nelem = x.nelem;
velem = x.velem;
vec = new BYTE[velem];
for (int i = 0; i < velem; i++)
vec[i] = x.vec[i];
}
}
// デストラクタ
~Array() { delete[] vec; }
// 要素数を返す
int size() const { return nelem; }
// 代入演算子
Array& operator=(const Array& x) {
if (&x != this) {
if (velem != x.velem) {
delete[] vec;
velem = x.velem;
vec = new BYTE[velem];
}
nelem = x.nelem;
for (int i = 0; i < velem; i++)
vec[i] = x.vec[i];
}
return *this;
}
// 添字演算子[]
BitOfByteRef operator[](int i) {
if (i < 0 || i >= nelem)
throw IdxRngErr(this, i);
return BitOfByteRef(
vec[i / CHAR_BITS], (i & (CHAR_BITS - 1))
);
}
// 添字演算子[]
bool operator[](int i) const {
if (i < 0 || i >= nelem)
throw IdxRngErr(this, i);
return
(vec[i / CHAR_BITS] >> (i & (CHAR_BITS - 1)) & 1U)
== 1;
}
};
#endif
// BoolArrayTest.cpp
#include <iostream>
#include "BoolArray.h"
using namespace std;
void print_Array_bool(const Array<bool>& a) {
for (int i = 0; i < a.size(); i++)
cout << (a[i] ? '1' : '0');
}
int main() {
Array<bool> x(10);
cout << boolalpha;
for (int i = 0; i < x.size(); i++)
cout << "x[" << i << "] = "
<< x[i] << '\n';
Array<bool> y(x);
Array<bool> z(5);
z = y;
y[3] = true; y[6] = true;
z[5] = true; z[7] = true;
cout << "x = ";
print_Array_bool(x); cout << '\n';
cout << "y = ";
print_Array_bool(y); cout << '\n';
cout << "z = ";
print_Array_bool(z); cout << '\n';
}
問題で与えられた BoolArray.h を、BoolArray.h と BoolArrayImplementation.h の2つに分けて、
インクルードモデルを実現しました。
// 解答
// Array.h
#ifndef ___ClassTemplateArray
#define ___ClassTemplateArray
template <class Type> class Array { };
#endif
// BoolArray.h
#ifndef ___ClassTemplateBoolArray
#define ___ClassTemplateBoolArray
#include <limits>
#include "Array.h"
template<> class Array<bool> {
typedef unsigned char BYTE;
static const int CHAR_BITS
= std::numeric_limits<unsigned char>::digits;
// bool型配列の要素数
int nelem;
// bool型配列を格納するためのBYTE型配列の要素数
int velem;
// BYTE型先頭要素へのポインタ
BYTE* vec;
// バイト型配列要素の必要数を算出
static int size_of(int sz);
public:
// 該当バイト中の該当ビットへの参照を表すクラス
class BitOfByteRef {
BYTE& vec; // 参照先BYTE
int idx; // 参照先BYTE中のビット番号
public:
// コンストラクタ
BitOfByteRef(BYTE& r, int i);
// 該当ビットを bool型で返却
operator bool() const;
// 該当ビットに true または false をセット
BitOfByteRef& operator=(bool b);
};
// 添字範囲エラー
class IdxRngErr {
const Array* ident;
int index;
public:
IdxRngErr(const Array* p, int i);
int Index() const;
};
// コンストラクタ
explicit Array(int sz, bool v = bool());
// コピーコンストラクタ
Array(const Array& x);
// デストラクタ
~Array();
// 要素数を返す
int size() const;
// 代入演算子
Array& operator=(const Array& x);
// 添字演算子[]
BitOfByteRef operator[](int i);
// 添字演算子[]
bool operator[](int i) const;
};
#include "BoolArrayImplementation.h"
#endif
// BoolArrayImplementation.h
#ifndef ___ClassTemplateBoolArrayImplementation
#define ___ClassTemplateBoolArrayImplementation
#include "Array.h"
int Array<bool>::size_of(int sz) {
return (sz + CHAR_BITS - 1) / CHAR_BITS;
}
Array<bool>::BitOfByteRef::
BitOfByteRef(BYTE& r, int i)
: vec(r), idx(i) { }
Array<bool>::BitOfByteRef::
operator bool() const {
return (vec >> idx) & 1U;
}
Array<bool>::BitOfByteRef& Array<bool>::
BitOfByteRef::operator=(bool b) {
if (b)
vec |= 1U << idx;
else
vec &= ~(1U << idx);
return *this;
}
Array<bool>::IdxRngErr::
IdxRngErr(const Array<bool>* p, int i)
: ident(p), index(i) { }
int Array<bool>::IdxRngErr::
Index() const { return index; }
Array<bool>::Array(int sz, bool v)
: nelem(sz), velem(size_of(sz)) {
vec = new BYTE[velem];
for (int i = 0; i < velem; i++)
vec[i] = v;
}
Array<bool>::Array(const Array<bool>& x) {
if (&x == this) {
nelem = 0;
vec = NULL;
}
else {
nelem = x.nelem;
velem = x.velem;
vec = new BYTE[velem];
for (int i = 0; i < velem; i++)
vec[i] = x.vec[i];
}
}
Array<bool>::~Array() { delete[] vec; }
int Array<bool>::size() const { return nelem; }
Array<bool>& Array<bool>::
operator=(const Array<bool>& x) {
if (&x != this) {
if (velem != x.velem) {
delete[] vec;
velem = x.velem;
vec = new BYTE[velem];
}
nelem = x.nelem;
for (int i = 0; i < velem; i++)
vec[i] = x.vec[i];
}
return *this;
}
Array<bool>::BitOfByteRef Array<bool>::
operator[](int i) {
if (i < 0 || i >= nelem)
throw IdxRngErr(this, i);
return BitOfByteRef(
vec[i / CHAR_BITS],
(i & (CHAR_BITS - 1))
);
}
bool Array<bool>::operator[](int i) const {
if (i < 0 || i >= nelem)
throw IdxRngErr(this, i);
return
(vec[i / CHAR_BITS] >>
(i & (CHAR_BITS - 1)) & 1U)
== 1;
}
#endif
// BoolArrayTest.cpp
#include <iostream>
#include "BoolArray.h"
using namespace std;
void print_Array_bool(const Array<bool>& a) {
for (int i = 0; i < a.size(); i++)
cout << (a[i] ? '1' : '0');
}
int main() {
Array<bool> x(10);
cout << boolalpha;
for (int i = 0; i < x.size(); i++)
cout << "x[" << i << "] = "
<< x[i] << '\n';
Array<bool> y(x);
Array<bool> z(5);
z = y;
y[3] = true; y[6] = true;
z[5] = true; z[7] = true;
cout << "x = ";
print_Array_bool(x); cout << '\n';
cout << "y = ";
print_Array_bool(y); cout << '\n';
cout << "z = ";
print_Array_bool(z); cout << '\n';
}
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/7256447
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック