1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #pragma once
18 
19 /** \file
20  * \ingroup freestyle
21  * \brief Simple RAII wrappers for std:: sequential containers
22  *
23  *  PointerSequence
24  *
25  *  Produces a wrapped version of a sequence type (std::vector, std::deque, std::list) that will
26  * take ownership of pointers that it stores.  Those pointers will be deleted in its destructor.
27  *
28  *  Because the contained pointers are wholly owned by the sequence, you cannot make a copy of the
29  * sequence. Making a copy would result in a double free.
30  *
31  *  This is a no-frills class that provides no additional facilities.  The user is responsible for
32  * managing any pointers that are removed from the list, and for making sure that any pointers
33  * contained in the class are not deleted elsewhere.  Because this class does no reference
34  * counting, the user must also make sure that any pointer appears only once in the sequence.
35  *
36  *  If more sophisticated facilities are needed, use tr1::shared_ptr or boost::shared_ptr.
37  *  This class is only intended to allow one to eke by in projects where tr1 or boost are not
38  * available.
39  *
40  *  Usage: The template takes two parameters, the standard container, and the class held in the
41  * container. This is a limitation of C++ templates, where T::iterator is not a type when T is a
42  * template parameter. If anyone knows a way around this limitation, then the second parameter can
43  * be eliminated.
44  *
45  *  Example:
46  *    PointerSequence<vector<Widget*>, Widget*> v;
47  *    v.push_back(new Widget);
48  *    cout << v[0] << endl; // operator[] is provided by std::vector, not by PointerSequence
49  *    v.destroy(); // Deletes all pointers in sequence and sets them to NULL.
50  *
51  *  The idiom for removing a pointer from a sequence is:
52  *    Widget* w = v[3];
53  *    v.erase(v.begin() + 3); // or v[3] = 0;
54  *  The user is now responsible for disposing of w properly.
55  */
56 
57 #include <algorithm>
58 
59 #ifdef WITH_CXX_GUARDEDALLOC
60 #  include "MEM_guardedalloc.h"
61 #endif
62 
63 namespace Freestyle {
64 
65 template<typename C, typename T> class PointerSequence : public C {
66   PointerSequence(PointerSequence &other);
67   PointerSequence &operator=(PointerSequence &other);
68 
destroyer(T t)69   static void destroyer(T t)
70   {
71     delete t;
72   }
73 
74  public:
PointerSequence()75   PointerSequence(){};
76 
~PointerSequence()77   ~PointerSequence()
78   {
79     destroy();
80   }
81 
destroy()82   void destroy()
83   {
84     for_each(this->begin(), this->end(), destroyer);
85   }
86 
87 #ifdef WITH_CXX_GUARDEDALLOC
88   MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:PointerSequence")
89 #endif
90 };
91 
92 } /* namespace Freestyle */
93