コンテナポインタ

コンテナポインタ.メイン.cpp
コンテナポインタ.h
ツリーコレクション.h


template<typename T> NAS6_Utl::NAS6_cntn_ptr
template<typename T> NAS6_Utl::NAS6_tree_clct
は、テンプレートベースのコンテナポインタとツリーコレクションです
コンテナポインタは、任意のクラスのスマートポインタとコンテナの機能があります
ツリーコレクションは、任意のクラスを木構造で管理するときに用います





■テンプレートベースのコンテナポインタ■
template<typename T> NAS6_Utl::NAS6_cntn_ptr<T>
コンテナポインタは、任意のクラスのスマートポインタとコンテナの機能があります

コンストラクタ
//peeper = true : 覗き見ポインタ
//delptr = true : 自動メモリ解放
//len : サイズ
NAS6_cntn_ptr(bool peeper = false, bool delptr = true);
NAS6_cntn_ptr(int len, bool delptr = true);
NAS6_cntn_ptr(NAS6_cntn_ptr<T>* rh);
NAS6_cntn_ptr(NAS6_cntn_ptr<T>& rh);

覗き見ポインタとは、メモリの所有権が制限され、リサイズなどが出来ませんが、メモリにアクセスできます
自動メモリ解放とは、メモリの所有権があるとき、管理するメモリを解放するかどうかです

int型ならば
NAS6_cntn_ptr<int> a(10);
NAS6_cntn_ptr<int> a = NAS6_cntn_ptr(10);
hoge型ならば
NAS6_cntn_ptr<hoge> b(1);
などとします


//セットピーパー : 設定は慎重に行ってください
NAS6_cntn_ptr<T>& setpeeper(bool rh);
//カレント
int current();
指示位置を取得します
//サイズ
int size();
サイズを取得します
//ポインタ
T* ptr();
管理メモリのアドレスを取得します
//オーナー
NAS6_cntn_ptr<T>* owner();
管理メモリの所有者のアドレスを取得します
//ピーパー
bool peeper();
覗き見ポインタであるかどうかです

a.begin(),a.end()a.at(rh) は指示メモリを移動します
*a で指示メモリを参照します
a[rh] は、ほぼ *(a.at(rh)) と等価です
++ -- + - 演算子で指示メモリの位置の移動ができます
*(a + 2) は、ほぼ a[a.current() + 2] と等価です
a = b で、bの管理メモリの所有権をaに移します。以降、bではアクセスできません
が、aが覗き見ポインタであった場合、bはなんの変化せず、aでbを覗けるようにできます

//利用メモリ割り当て&メモリ所有権新規取得
NAS6_cntn_ptr<T>& assign(T* rh, const int len);
rhのメモリを管理するように割り当てます。自動メモリ解放がtrueであったら、古いメモリは解放されます
lenはrhのサイズです

//リサイズ
//force = true : 強制 : コピー&リサイズ&メモリ所有権新規取得
NAS6_cntn_ptr<T>& resize(const int len, const bool force = false);
lenでリサイズします。forceがtrueであったら、強制的に実行します

//リムーブ
NAS6_cntn_ptr<T>& remove(const int rh);
管理メモリの中のrhの位置を取り除きます

//アッド
NAS6_cntn_ptr<T>& add(const int rh, T& trh);
管理メモリの中のrhの位置にtrhを追加する


//コピー&リサイズ&メモリ所有権新規取得 : peeper = true : rhを覗き見ポインタにする : destroy = true : rhをアクセス不可にする
NAS6_cntn_ptr<T>& copyFrom(NAS6_cntn_ptr<T>& rh, int len = -1, bool peeper = false, bool destroy = false);
rhから自身に、新規にメモリを確保してコピーを実行します。メモリの所有権は両方にあります
lenはサイズです。-1の場合はrhのサイズとなります





■テンプレートベースのツリーコレクション■
template<typename T> NAS6_Utl::NAS6_tree_clct<T>
ツリーコレクションは、任意のクラスを木構造で管理するときに用います

コンストラクタ
//NAS6_cntn_ptr<T>への設定
//peeper = true : 覗き見ポインタ
//delptr = true : 自動メモリ解放
//len : サイズ
NAS6_tree_clct(bool peeper = false, bool delptr = true);
NAS6_tree_clct(int len, bool delptr = true);
//コピーコンストラクタはピーパー
NAS6_tree_clct(NAS6_tree_clct<T>* rh);
NAS6_tree_clct(NAS6_tree_clct<T>& rh);

int型ならば
NAS6_tree_clct<int> a(10);
NAS6_tree_clct<int> a = NAS6_tree_clct<int>(10);
hoge型ならば
NAS6_tree_clct<hoge> b;
などとします

サイズ指定は、親クラスのNAS6_cntn_ptr<T>の設定です


//祖先かどうか
bool isancestor(NAS6_tree_clct<T>* rh);
//ルート
NAS6_tree_clct<T>& getroot();
ルートへの参照を取得します
//キー
NAS6_cntn_ptr<string>& key();
キーの管理メモリへの参照を取得します
string& key(int rh);
rh番目の子のキーを取得します
string& thiskey();
自身のキーを取得します
//親
NAS6_tree_clct<T>& parent();
親への参照を取得します
//子
NAS6_cntn_ptr<NAS6_tree_clct<T>*>& child();
子の管理メモリへの参照を取得します
NAS6_tree_clct<T>& child(int rh);
rh番目の子への参照を取得します
NAS6_tree_clct<T>*& childptr(int rh);
子の管理メモリへのポインタ参照を取得します
//何番目の子か
int childnum();
自身が何番目の子であるか
//キーの一致 : 一致したら、キー内の何文字目かを返し、一致しなかったら、string::nposを返す
int conformkey(NAS6_tree_clct<T>* rh, string fk);
//コピー&リサイズ&メモリ所有権新規取得 : peeper = true : rhを覗き見ポインタにする : peeper = false : rhをアクセス不可にする
NAS6_tree_clct<T>& tc_copyFrom(NAS6_tree_clct<T>* rh, bool peeper = true, bool b = true);
//rhを覗き見する
NAS6_tree_clct<T>& tc_peepTo(NAS6_tree_clct<T>* rh, bool b = true);


//子生成
//n : n番目に子を追加生成する : -1 : 一番後ろに追加する
//resetkey = true : rhのキーのリセット
NAS6_tree_clct<T>& deliver(string key = "", int n = -1, NAS6_tree_clct<T>* rh = nullptr, bool resetkey = true);
keyは子に紐づけられた、string文字列です
rhを子に紐づけます。rhがnullptrであったら、新規に子を生成します

NAS6_tree_clct<T> a;
a.deliver();
a.deliver("keytest1");
a.deliver("keytest2");
a.child(0).deliver();
a.child(0).deliver();
a.child(0).child(1).deliver();
a.child(2).deliver();
a.child(2).deliver("keytest");
a.child(2).child(0).deliver();

↑するとaが↓のように子が生成されています

//delivered
//0:0:0
//  :1:0
// :1 > keytest1
// :2 > keytest2
//  :0:0
//  :1 > keytest

delete &(a.child(2)); で、0:2以下を再帰的に破棄します

NAS6_tree_clct<T> b;
b.deliver("keytest");
b.deliver();
b.child(1).deliver();
b.child(1).deliver();
b.child(1).child(1).deliver("keytest");

↑するとbが↓のように子が生成されています

//delivered
//0:0 > keytest
// :1:0
//  :1:0 > keytest

a.deliver("keytest3", 1, &(b)); //bはpeeperになる

それから、↑するとaが↓のように子が生成されています

//delivered
//0:0:0
//  :1:0
// :1 > keytest3
//  :0 > keytest
//  :1:0
//   :1:0 > keytest
// :2 > keytest1


//再帰構文例1
template
void recHoge1(NAS6_tree_clct* root, string fk) {
 bool parent = false;
 if (&root->recursiveInit() == nullptr) return;
 NAS6_tree_clct* crnt = root;
 //crnt = root; の時のcrntに適用の処理
 //or : //if (crnt->conformkey(crnt, fk) != string::npos) //{...} //キー検索の時
 while (!crnt->recursiveIsEnd(root)) {
  parent = false;
  crnt = &(crnt->recursiveNext(root), parent);
  //or : //crnt = &(crnt->recursiveKeyNext(root, fk, parent));
  //if(!parent) //{...} //crnt = Next; の時のcrntに適用の処理
  //else //{...} //親に戻った時の処理
 }
}

//再帰構文例2
{ //other scope
 bool b = false;
 recHoge2(&tree_c, b); //call
}
template
NAS6_tree_clct& recHoge2(NAS6_tree_clct* rh, bool& parent) {
 int ncrnt = 0;
 // rhに適用の処理 // if(!parent){...}else{...}
 if (rh->child().size() == ncrnt) { parent = true; return (rh->parent()); }
 while (rh->child().size() != ncrnt) {
  ncrnt++;
  parent = false;
  recHoge2(&(rh->child(ncrnt - 1)), parent);
 }
 return (*rh);
}

再帰構文は、大体こんな感じで実装します

NAS6_tree_clct<T>& recursiveNext(NAS6_tree_clct<T>* root, bool& parent);
root以下を全検索をするときに使用します
bool parent = false;の実体を渡してください

//キー検索
NAS6_tree_clct<T>& recursiveKeyNext(NAS6_tree_clct<T>* root, const string fk, bool& parent);
root以下をfkと一致するキー検索をするときに使用します
bool parent = false;の実体を渡してください


メイン.cppの冒頭の
//#define CHK_MEM_LEAK
をコメントアウトをしないと、メモリリークチェックモードになります
あと、main()の
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
がメモリリークチェック関数です





戻る