Rheolef  7.2
an efficient C++ finite element environment
 
Loading...
Searching...
No Matches
smart_pointer.h
Go to the documentation of this file.
1#ifndef _RHEO_SMART_POINTER_H
2#define _RHEO_SMART_POINTER_H
3//
4// This file is part of Rheolef.
5//
6// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
7//
8// Rheolef is free software; you can redistribute it and/or modify
9// it under the terms of the GNU General Public License as published by
10// the Free Software Foundation; either version 2 of the License, or
11// (at your option) any later version.
12//
13// Rheolef is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with Rheolef; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21//
22// =========================================================================
23// author: Pierre.Saramito@imag.fr
24// date: 27 january 2000, updated 11 may 2012.
25
26namespace rheolef {
121} // namespace rheolef
122
123#include "rheolef/compiler.h"
124
125// -----------------------------------------------------------------------
126// smart_pointer_base<T,Copy>
127// -----------------------------------------------------------------------
128namespace rheolef {
129
130template <class T, class C>
132public:
133
134 struct internal {};
135
136// allocators:
137
140 smart_pointer_base (void* count, internal);
143
144// accessors:
145
146 const T* pointer () const;
147 const T& data () const;
148 const T* operator-> () const;
149 const T& operator* () const;
150
151// modifiers:
152
154 T& data ();
157
158// implementation:
159private:
160 struct counter {
161 T* _p;
162 int _n;
163 counter (T* p = 0);
164 ~counter ();
165#pragma GCC diagnostic push
166#pragma GCC diagnostic ignored "-Weffc++"
167 int operator++ ();
168 int operator-- ();
169#pragma GCC diagnostic pop
170 private:
171 counter (const counter&);
172 counter& operator= (const counter&);
173 };
174 counter *_count;
175public:
176#ifndef TO_CLEAN
177 int reference_counter() const { return _count != 0 ? _count->_n : -1; }
178#endif // TO_CLEAN
179 counter* get_count() const { return _count; }
180};
181// -----------------------------------------------------------------------
182// counter: inlined
183// -----------------------------------------------------------------------
184template <class T, class C>
185inline
186smart_pointer_base<T,C>::counter::counter (T* p)
187 : _p(p), _n(1)
188{
189}
190template <class T, class C>
191inline
192smart_pointer_base<T,C>::counter::~counter ()
193{
194 delete_macro(_p);
195}
196#pragma GCC diagnostic push
197#pragma GCC diagnostic ignored "-Weffc++"
198template <class T, class C>
199inline
200int
201smart_pointer_base<T,C>::counter::operator++ ()
202{
203 return ++_n;
204}
205template <class T, class C>
206inline
207int
208smart_pointer_base<T,C>::counter::operator-- ()
209{
210 if (--_n != 0) return _n;
211 delete(this);
212 return 0;
213}
214#pragma GCC diagnostic pop
215// -----------------------------------------------------------------------
216// smart_pointer_base: inlined
217// -----------------------------------------------------------------------
218template <class T, class C>
219inline
221: _count(new_macro(counter(p)))
222{
223}
224template <class T, class C>
225inline
227: _count(static_cast<counter*>(count))
228{
229 ++(*_count);
230}
231template <class T, class C>
232inline
234 : _count(sp._count)
235{
236 ++(*_count);
237}
238template <class T, class C>
239inline
241{
242 if (_count != 0) { --(*_count); }
243}
244template <class T, class C>
245inline
248{
249 if (_count != sp._count) {
250 --(*_count);
251 _count = sp._count;
252 ++(*_count);
253 }
254 return *this;
255}
256template <class T, class C>
257inline
258const T*
260{
261 return _count -> _p;
262}
263template <class T, class C>
264inline
265const T&
267{
268 return *pointer();
269}
270template <class T, class C>
271inline
272const T*
274{
275 return pointer();
276}
277template <class T, class C>
278inline
279const T&
281{
282 return data();
283}
284template <class T, class C>
285inline
286T*
288{
289 // here is tthe true copy semantic:
290 if (_count -> _p == 0) return 0;
291 if (_count -> _n > 1) {
292 --(_count-> _n);
293 T* q = C()(*(_count -> _p));
294 _count = new_macro (counter(q));
295 }
296 return _count -> _p;
297}
298template <class T, class C>
299inline
300T*
302{
303 return pointer();
304}
305template <class T, class C>
306inline
307T&
309{
310 return *pointer();
311}
312template <class T, class C>
313inline
314T&
316{
317 return data();
318}
319// -----------------------------------------------------------------------
320// copy functors implementing the three possible copy semantics
321// -----------------------------------------------------------------------
322namespace details {
323
324// constructor_copy uses the copy constructor of the object - used for simple types
325template <typename T>
326struct constructor_copy {
327 T* operator() (const T& data) throw() { return new_macro(T(data)); }
328};
329
330// clone_copy uses the clone method of the object - used for polymorphic types
331template <typename T>
332struct clone_copy {
333 T* operator() (const T& from) throw() { return from.clone(); }
334};
335
336// no_copy throws an exception - used for types that cannot be copied
337template <typename T>
338struct no_copy {
339 T* operator() (const T& from) {
340 error_macro ("no_copy functor called (illegal copy)");
341 return 0;
342 }
343};
344
345} // end namespace stlplus
346// -----------------------------------------------------------------------
347// smart_pointer<T>
348// -----------------------------------------------------------------------
349// [verbatim_smart_pointer]
350template <typename T>
351class smart_pointer : public smart_pointer_base<T, details::constructor_copy<T> > {
352 typedef details::constructor_copy<T> C;
353 typedef smart_pointer_base<T,C> base;
354 public:
356 typedef typename base::internal internal;
357 smart_pointer (T* p = 0) : base (p) {}
358 smart_pointer (void* count, internal i) : base(count,i) {}
359 smart_pointer (const smart_pointer<T>& x) : base(x) {}
361 base::operator= (x); return *this; }
363};
364// [verbatim_smart_pointer]
365// -----------------------------------------------------------------------
366// smart_pointer_clone<T>
367// -----------------------------------------------------------------------
368// [verbatim_smart_pointer_clone]
369template <typename T>
370class smart_pointer_clone : public smart_pointer_base<T, details::clone_copy<T> > {
371 typedef details::clone_copy<T> C;
372 typedef smart_pointer_base<T,C> base;
373 public:
375 typedef typename base::internal internal;
376 smart_pointer_clone (T* p = 0) : base (p) {}
377 smart_pointer_clone (void* count, internal i) : base(count,i) {}
380 base::operator= (x); return *this; }
382};
383// [verbatim_smart_pointer_clone]
384// -----------------------------------------------------------------------
385// smart_pointer_nocopy<T>
386// -----------------------------------------------------------------------
387// [verbatim_smart_pointer_nocopy]
388template <typename T>
389class smart_pointer_nocopy : public smart_pointer_base<T, details::no_copy<T> > {
390 typedef details::no_copy<T> C;
391 typedef smart_pointer_base<T,C> base;
392 public:
394 typedef typename base::internal internal;
395 smart_pointer_nocopy (T* p = 0) : base (p) {}
396 smart_pointer_nocopy (void* count, internal i) : base(count,i) {}
399 base::operator= (x); return *this; }
401};
402// [verbatim_smart_pointer_nocopy]
403}// namespace rheolef
404#endif // _RHEO_SMART_POINTER_H
405
406#ifdef _RHEO_SMART_POINTER_TST_CC
407// -----------------------------------------------------------------------
408// smart_pointer_tst.cc : here for doxygen, to avoid INPUT in util/tst
409// -----------------------------------------------------------------------
410using namespace rheolef;
411using namespace std;
412
413// [verbatim_smart_pointer_tst]
414// data representation (could be file "container_data.h")
415typedef int T;
416class container_data {
417 private:
418 T *values;
419 int n;
420 public:
426 container_data (const container_data& x)
427 : values(new T[x.n]), n(x.n)
428 { for (int i=0; i<n;i++) values[i]=x.values[i];}
429 container_data& operator= (const container_data& x) {
430 n = x.n;
431 values = new T[n];
432 for (int i=0; i<n;i++) values[i]=x.values[i];
433 return *this;
434 }
435 // a customized constructor
436 explicit container_data(int n1)
437 : values(new T[n1]), n(n1) {}
438
439 ~container_data() { delete [] values; }
440
441 // read and write accessors are separated
442 const T& operator[](int i) const
443 { return values[i]; }
444 T& operator[](int i)
445 { return values[i]; }
446};
447// an interface to data via the Objet class
448// that count occurrence (could be "container.h")
449//
450class container : private smart_pointer<container_data> {
451public:
452 // the customized cstor
453 explicit container(int n = 0);
454
455 // read/write accessors
456 const T& operator[](int i) const;
457 T& operator[](int i);
458};
459// here is the implementation of the interface
460// (could be "container.c")
461//
462container::container (int n)
463: smart_pointer<container_data> (new container_data(n))
464{}
465const T&
466container::operator[] (int i) const {
467 // use read access data()
468 return data().operator[] (i);
469}
470T&
471container::operator[] (int i) {
472 // use write access data() that check occurrence count
473 return data().operator [] (i);
474}
475// test program
476int main() {
477 container A(10);
478 A[1] = 1;
479 container B = A;
480 B[1] = 2;
481 if (A[1] == B[1]) {
482 std::cerr << "fatal: It is not a true copy semantic." << std::endl;
483 exit(1);
484 }
485 std::cerr << "It seems to be a true copy semantic." << std::endl;
486}
487// [verbatim_smart_pointer_tst]
488#endif // _RHEO_SMART_POINTER_TST_CC
smart_pointer_base(void *count, internal)
const T & operator*() const
counter * get_count() const
smart_pointer_base(const smart_pointer_base< T, C > &)
const T * operator->() const
smart_pointer_base< T, C > & operator=(const smart_pointer_base< T, C > &)
smart_pointer_clone(const smart_pointer_clone< T > &x)
smart_pointer_clone< T > & operator=(const smart_pointer_clone< T > &x)
smart_pointer_clone(void *count, internal i)
smart_pointer_nocopy(const smart_pointer_nocopy< T > &x)
smart_pointer_nocopy< T > & operator=(const smart_pointer_nocopy< T > &x)
smart_pointer_nocopy(void *count, internal i)
see the smart_pointer page for the full documentation
smart_pointer(void *count, internal i)
base::internal internal
smart_pointer< T > & operator=(const smart_pointer< T > &x)
smart_pointer(const smart_pointer< T > &x)
#define error_macro(message)
Definition dis_macros.h:49
int main()
Definition field2bb.cc:58
Expr1::float_type T
Definition field_expr.h:230
This file is part of Rheolef.
STL namespace.
Definition sphere.icc:25