今回のバージョンアップで要素間の接続に用いるポインタを全て shared_ptr に変更しているのですが
this ポインタを使用する必要がある所が出てきて躓きました。二重に開放してはいけないからといって
shared_ptr<T>(this, [](T*){})
という風に何もしないデリーターを渡してもダメな気がします。
同じオブジェクトを二重に参照管理することになりますし。
これは設計からやり直さないとだめかなーと思ったら、ちゃんとあるんですね this ポインタを shared_ptr にする方法が。
this ポインタを shared_ptr に変換するインタフェースクラスを継承して
class T : public std::enable_shared_from_this<T>
shared_from_this() を呼び出すだけ。助かりしました(^^;
実験プログラムソースコード
// compiler Visual C++ 2019
// 木構造実験プログラム
#include <iostream>
#include <vector>
#include <string>
// 木構造基底アイテム
struct tree_item : public std::enable_shared_from_this<tree_item>
{
using ptr_type = typename std::shared_ptr<tree_item>; // ポインタタイプ
using ctr_type = typename std::vector<ptr_type>; // コンテナタイプ
virtual ~tree_item() {}
virtual ctr_type& Branch() { throw "未実装例外"; }
virtual bool parse(std::istream& is, ptr_type parent) = 0;
virtual void print(const size_t level = 0) = 0;
};
// 葉アイテム
struct tree_leaf : public tree_item
{
std::string text;
virtual ~tree_leaf() {}
virtual bool parse(std::istream& is, ptr_type parent) override
{
text.clear();
while (is)
{
auto c = is.get();
if (c == std::istream::traits_type::eof())
{
break;
}
if ((c == '{') || (c == '}'))
{
is.unget();
break;
}
if (c == ';' || c == '\n')
{
break;
}
text += c;
}
if (text.size() > 0)
{
parent->Branch().push_back(shared_from_this());
return true;
}
return false;
}
virtual void print(const size_t level = 0) override
{
for (size_t i = 0; i < level; ++i) std::cout << '\t';
std::cout << typeid(this).name() << std::endl;
}
};
// 節アイテム
struct tree_node : public tree_item
{
ctr_type branch;
virtual ~tree_node() {}
virtual ctr_type& Branch() { return branch; }
virtual bool parse(std::istream& is, ptr_type parent) override
{
if (is.peek() != '{')
{
return false;
}
is.get();
while (is)
{
if (ptr_type(new tree_node)->parse(is, shared_from_this()))
{
continue;
}
if (ptr_type(new tree_leaf)->parse(is, shared_from_this()))
{
continue;
}
if (is.peek() == '}')
{
is.get();
parent->Branch().push_back(shared_from_this());
return true;
}
}
return false;
}
virtual void print(const size_t level = 0) override
{
for (size_t i = 0; i < level; ++i) std::cout << '\t';
std::cout << typeid(this).name() << std::endl;
for (auto n : branch)
{
n->print(level + 1);
}
}
};
// 根アイテム
struct tree_root : public tree_node
{
virtual ~tree_root() {}
virtual bool parse(std::istream& is, ptr_type parent) override
{
while (is)
{
if (ptr_type(new tree_node)->parse(is, shared_from_this()))
{
continue;
}
if (ptr_type(new tree_leaf)->parse(is, shared_from_this()))
{
continue;
}
}
return true;
}
virtual void print(const size_t level = 0) override
{
for (size_t i = 0; i < level; ++i) std::cout << '\t';
std::cout << typeid(this).name() << std::endl;
for (auto n : branch)
{
n->print(level + 1);
}
}
};
int main()
{
auto root = tree_item::ptr_type( new tree_root );
std::cout << "*** input" << std::endl;
root->parse(std::cin, nullptr);
std::cout << "*** print" << std::endl;
root->print();
}