C ++ template tree question template

I just came across a beautiful STL-like tree container class written by Kasper Peeters:

http://tree.phi-sci.com/

However, since it is similar to STL, it focuses on having one type of class in the tree; those. template <class T>. A problem is related to STL lists if it suffers from a polymorphic class problem, since objects in the tree that are pointers to objects with heaps (for example, pointers to a base class) are not destroyed when nodes are deleted.

So my options are:

1: use the boost :: shared_ptr tree, although it's more expensive / overkill than we would like.

2: Write a small pointer wrapper, such as the one I wrote below. The idea is that it wraps a pointer, which when it goes out of scope removes its pointer. This is not a ref count, it just ensures that the pointer is destroyed.

template<class T>
class TWSafeDeletePtr
{
private:
    T *_ptr;
public:
    TWSafeDeletePtr() : _ptr(NULL) {}
    TWSafeDeletePtr(T *ptr) : _ptr(ptr) {}
    ~TWSafeDeletePtr()
    { 
        delete _ptr;
    }
    T &operator=(T *ptr)
    {
        assert(!_ptr);
        delete _ptr;
        _ptr=ptr;
        return *ptr;
    }
    void set(T *ptr)
    {
        *this=ptr;
    }

    T &operator*() const { return *_ptr; }
    T *operator->() const { return _ptr; }
};

3: write my own dispenser that selects node objects from the pool in allocate () and deletes the marked ones in memory in deallocate ().

4: Specialize code to create a pointer tree, avoiding the initial distribution and creation of a copy, as well as the inherent knowledge of deleting deleted data.

2, , ptr, () , . , , , , , , , . . , , .

3 , , , - - ?

, 1 (tree of shared_ptrs), , , , node . :)

,

+3
7

, , . , , , ; , .

, , -, - alloc_.allocate x ( 886):

tree_node* tmp = alloc_.allocate(1,0);
kp::constructor(&tmp->data, x);

, , , , - node , ( 1000):

template <class T, class tree_node_allocator>
template <class iter>
iter tree<T, tree_node_allocator>::replace(iter position, const T& x)
    {
    kp::destructor(&position.node->data);
    kp::constructor(&position.node->data, x);
    return position;
    }

, ; , ( x , , .)

, , - , , , shared_ptr.

+1

[] boost:: shared_ptr , . / ( , ), (, ) , № 5. № 2, (: auto_ptr ).

, № 5.

1: boost:: shared_ptr, /, .

, , , std:: list, std:: set, std:: map, / node, ? , - , - .

2: , , . , , . ref count, .

, , . , , , , -, node.

3: , node allocate() deallocate().

STL- , deallocate. , , , . , , malloc/free, , , .

4: , , , .

, , . , () , .

№ 5: .

, . map<int, ExpensiveElement*> map<int, shared_ptr<ExpensiveElement> > map<int, ExpensiveElement>.

, , , , ( node ). , .

, -, ( ctor ExpensiveElement). ! [] insert:

map<int, ExpensiveElement> my_map;

// default constructs ExpensiveElement 
// and calls ExpensiveElement::do_something().
// No copies of ExpensiveElement are made!
my_map[7].do_something();

! , , / .

ExpensiveElement , , ( ) .

map<int, ExpensiveElement> my_map;

// construct an ExpensiveElement and swap it into the map
// this avoids redundant work and copying and can be very 
// efficient if the default constructor of ExpensiveElement
// is cheap to call
ExpensiveElement element(...);
my_map[7].swap(element);

, ExpensiveElement. , ctor pimpl, , swap pimpls ExpensiveElement. ExpensiveElements , .

, ExpensiveElement ctor?

, . , , () . ctor pointee, , . , , , ; , boost:: shared_ptr, . , .

, ?

. , ( ), .

+1

, . ++ 0x.

Boost Pointer Container STL ... .

, , - . , .

, , -, (clone ). , ... , .

/// Requirement: T is a model of Cloneable
template <class T>
class Proxy
{
  template <class> friend class Proxy;
public:
  // Constructor
  Proxy(): mPointer(0) {}
  explicit Proxy(T* t): mPointer(t) {}
  template <class U>
  explicit Proxy(std::auto_ptr<U> t): mPointer(t.release()) {}
  template <class U>
  explicit Proxy(std::unique_ptr<U> t): mPointer(t.release()) {}

  // Copy Constructor
  Proxy(Proxy const& rhs):
    mPointer(rhs.mPointer ? rhs.mPointer->clone() : 0) {}
  template <class U>
  Proxy(Proxy<U> const& rhs):
    mPointer(rhs.mPointer ? rhs.mPointer->clone() : 0) {}

  // Assignment Operator
  Proxy& operator=(Proxy const& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }
  template <class U>
  Proxy& operator=(Proxy<U> const& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }

  // Move Constructor
  Proxy(Proxy&& rhs): mPointer(rhs.release()) {}
  template <class U>
  Proxy(Proxy<U>&& rhs): mPointer(rhs.release()) {}

  // Move assignment
  Proxy& operator=(Proxy&& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }
  template <class U>
  Proxy& operator=(Proxy&& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }

  // Destructor
  ~Proxy() { delete mPointer; }

  void swap(Proxy& rhs)
  {
    T* tmp = rhs.mPointer;
    rhs.mPointer = mPointer;
    mPointer = tmp;
  }

  T& operator*() { return *mPointer; }
  T const& operator*() const { return *mPointer; }

  T* operator->() { return mPointer; }
  T const* operator->() const { return mPointer; }

  T* release() { T* tmp = mPointer; mPointer = 0; return tmp; }

private:
  T* mPointer;
};

// Free functions
template <class T>
void swap(Proxy<T>& lhs, Proxy<T>& rhs) { lhs.swap(rhs); }

, , , . .

static_cast dynamic_cast, ;)

0

, Boost Pointer Container. . , "" typedefs - , .

0

, 1, , . shared_ptr , , . map_obj[key].reset(new ValueType);?

, 2 shared_ptr, shared_ptr , .

3 , . allocate/construct deallocate/destruct , node .

, , . , , shared_ptr , , .

0

1 (tree of shared_ptrs), , , , node . :)

0

1.

1, , ptr, () , . , , , , , , , . . , , .

shared_ptr, , , .

2. . shared_ptr.

3. , , .

4. .

1.

-1

Source: https://habr.com/ru/post/1752059/


All Articles