Browse Source

Test: PityTree - RValue refs, copy constructor, addRef/addCopy/addNew

Tree can now own or reference nodes, mixed.
master
heck 4 years ago
parent
commit
45be1fe127
  1. 28
      src/PityTree.hh
  2. 71
      src/PityTree.hxx

28
src/PityTree.hh

@ -17,17 +17,32 @@ namespace pEp {
template<class T>
class PityTree {
// TODO: NEEEEED THIS
// static_assert(std::is_base_of<PityTree<T>, T>::value, "PityTree<T> must be a base of T");
// static_assert(std::is_base_of<PityTree<T>, T>::value, "PityTree<T> must be a base of T");
public:
using Children = std::map<const std::string, T&>;
using ChildObj = std::shared_ptr<T>;
using ChildObjs = std::vector<ChildObj>;
using ChildRef = std::pair<const std::string, T&>;
using ChildRefs = std::map<const std::string, T&>;
// Constructors
explicit PityTree(T& self, const std::string& name);
explicit PityTree(T& self, const std::string& name, T& parent);
explicit PityTree(const PityTree& rhs, T& owner);
T& add(T& node);
virtual PityTree* clone() = 0;
// Append
T& addRef(T& node);
template<typename... Args>
T& addNew(Args&&... args);
template<typename CT>
T& addCopy(const CT&& t, const std::string& new_name = "");
// Query
T* getParent() const;
Children getChildren() const;
ChildRefs getChildRefs() const;
T& getChild(const std::string& name);
T& getRoot();
@ -50,8 +65,9 @@ namespace pEp {
// Fields
std::string _nodename;
T& _self;
T* _parent = nullptr; //nullptr if RootUnit
Children _children; // map to guarantee uniqueness of sibling-names
T* _parent; //nullptr if RootUnit
ChildRefs _childrefs; // map to guarantee uniqueness of sibling-names
ChildObjs _childobjs;
};
}; // namespace PityTest11
}; // namespace pEp

71
src/PityTree.hxx

@ -15,32 +15,77 @@
#include <memory>
#include <unordered_map>
#include <sys/wait.h>
#include "PityTree.hh"
namespace pEp {
namespace PityTest11 {
// RootNode
template<class T>
PityTree<T>::PityTree(T& self, const std::string& name) :
_self{ self }, _nodename{ _normalizeName(name) }
_self{ self }, _parent{ nullptr }, _nodename{ _normalizeName(name) }, _childrefs{},
_childobjs{}
{
}
// LeafNode
template<class T>
PityTree<T>::PityTree(T& self, const std::string& name, T& parent) :
_self(self), _nodename{ _normalizeName(name) }
_self(self), _parent{ nullptr }, _nodename{ _normalizeName(name) }, _childrefs{},
_childobjs{}
{
parent.add(_self);
parent.addRef(_self);
}
// Copy
template<class T>
T& PityTree<T>::add(T& node)
PityTree<T>::PityTree(const PityTree<T>& rhs, T& owner) : _self{ owner }
{
_nodename = rhs._nodename;
_parent = nullptr;
for (const ChildRef& cr : rhs.getChildRefs()) {
_childobjs.push_back(ChildObj(cr.second.clone()));
T& ret = *_childobjs.back().get();
addRef(ret);
}
}
template<class T>
T& PityTree<T>::addRef(T& node)
{
node.setParent(&_self);
_children.insert(std::pair<const std::string, T&>(node.getName(), node));
_childrefs.insert(ChildRef(node.getName(), node));
return node;
}
template<typename T>
template<typename... Args>
T& PityTree<T>::addNew(Args&&... args)
{
_childobjs.push_back(ChildObj(new T(std::forward<Args>(args)...)));
T& ret = *_childobjs.back().get();
addRef(ret);
return ret;
}
template<typename T>
template<typename CT>
T& PityTree<T>::addCopy(const CT&& t, const std::string& new_name)
{
static_assert(std::is_base_of<T, CT>::value, "PityTree<T> must be a base of T");
_childobjs.push_back(ChildObj(new CT(t)));
T& ret = *_childobjs.back().get();
if (new_name != "") {
ret.setName(new_name);
}
addRef(ret);
return ret;
}
template<class T>
void PityTree<T>::setParent(T* parent)
{
@ -99,9 +144,9 @@ namespace pEp {
ret = builder.str();
if (recursive) {
if (!getChildren().empty()) {
if (!getChildRefs().empty()) {
indent++;
for (auto child : getChildren()) {
for (ChildRef child : getChildRefs()) {
ret += child.second.to_string(true, indent);
}
indent--;
@ -121,15 +166,21 @@ namespace pEp {
}
template<class T>
typename PityTree<T>::Children PityTree<T>::getChildren() const
typename PityTree<T>::ChildRefs PityTree<T>::getChildRefs() const
{
return _children;
return _childrefs;
}
template<class T>
T& PityTree<T>::getChild(const std::string& name)
{
return _children.at(name);
T* ret = nullptr;
try {
ret = &getChildRefs().at(name);
} catch (const std::exception& e) {
throw std::invalid_argument("PityNode not found: '" + name + "'");
}
return *ret;
}
// name is alphanumeric only (everything else will be replaced by an underscore)

Loading…
Cancel
Save