A few days ago, I took on the task of trying to write a basic tree implementation in the same style as STL containers. Now I'm trying to use it in my code, but two things do not seem to work, and they work with std::vector . Namely, using incomplete types and using abstract types.
How to fix my tree implementation to get this functionality? I tried to slightly condens my code to show you basically the relevant parts.
test.cpp
#include "util/tree.hpp" #include <vector> struct IncompleteType; class AbstractType { public: virtual void do_something() = 0; }; class Test { public: Test() = default; private: tree<IncompleteType> incompleteTree; std::vector<IncompleteType> incompleteVector; tree<AbstractType> abstractTree; std::vector<AbstractType> abstractVector; }; struct IncompleteType { int completed; };
util / tree.hpp (with compaction)
template <class T, class Alloc = std::allocator<T> > class tree { public: typedef Alloc allocator_type; typedef typename Alloc::value_type value_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename Alloc::difference_type difference_type; typedef typename Alloc::size_type size_type; class node { public: value_type data; const std::vector<std::unique_ptr<node> >& get_children() const { return children_; } node* get_parent() const { return parent_; } node* get_right() const { return right_; } bool operator== (const node&) const; size_t size() const; bool has_ancestor(const node* n) const { return parent_ != nullptr && (parent_ == n || parent_->has_ancestor(n)); } friend class tree; protected: std::vector<std::unique_ptr<node> > children_; node* parent_ = nullptr; node* right_ = nullptr; node() = default; node(value_type data) : data(data) {} }; class iterator {
When compiling with g++ -O3 -Wall -Wextra -pedantic -std=c++11 test.cpp I get the following output:
In file included from test.cpp:1:0: util/tree.hpp: In instantiation of 'class tree<IncompleteType>::node': util/tree.hpp:138:7: required from 'class tree<IncompleteType>' test.cpp:19:30: required from here util/tree.hpp:28:14: error: 'tree<T, Alloc>::node::data' has incomplete type value_type data; ^ test.cpp:6:8: error: forward declaration of 'tree<IncompleteType>::value_type {aka struct IncompleteType}' struct IncompleteType; ^ In file included from test.cpp:1:0: util/tree.hpp: In instantiation of 'class tree<AbstractType>::node': util/tree.hpp:138:7: required from 'class tree<AbstractType>' test.cpp:21:30: required from here util/tree.hpp:47:3: error: cannot allocate an object of abstract type 'AbstractType' node(value_type data) : data(data) {} ^ test.cpp:8:7: note: because the following virtual functions are pure within 'AbstractType': class AbstractType ^ test.cpp:11:15: note: virtual void AbstractType::do_something() virtual void do_something() = 0; ^ In file included from test.cpp:1:0: util/tree.hpp:28:14: error: cannot declare field 'tree<AbstractType>::node::data' to be of abstract type 'AbstractType' value_type data; ^ test.cpp:8:7: note: since type 'AbstractType' has pure virtual functions class AbstractType ^
My tree has problems with these types, while std::vector does not. I see that this is due to the way I store the data inside the nodes, but I draw a space trying to come up with the right way to do this ... How to store things, if not of type value_type ?
c ++ abstract-class stl tree incomplete-type
robrene
source share