Rheolef  7.2
an efficient C++ finite element environment
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 
26 namespace rheolef {
121 } // namespace rheolef
122 
123 #include "rheolef/compiler.h"
124 
125 // -----------------------------------------------------------------------
126 // smart_pointer_base<T,Copy>
127 // -----------------------------------------------------------------------
128 namespace rheolef {
129 
130 template <class T, class C>
132 public:
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 
153  T* pointer ();
154  T& data ();
157 
158 // implementation:
159 private:
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;
175 public:
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 // -----------------------------------------------------------------------
184 template <class T, class C>
185 inline
186 smart_pointer_base<T,C>::counter::counter (T* p)
187  : _p(p), _n(1)
188 {
189 }
190 template <class T, class C>
191 inline
192 smart_pointer_base<T,C>::counter::~counter ()
193 {
194  delete_macro(_p);
195 }
196 #pragma GCC diagnostic push
197 #pragma GCC diagnostic ignored "-Weffc++"
198 template <class T, class C>
199 inline
200 int
201 smart_pointer_base<T,C>::counter::operator++ ()
202 {
203  return ++_n;
204 }
205 template <class T, class C>
206 inline
207 int
208 smart_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 // -----------------------------------------------------------------------
218 template <class T, class C>
219 inline
221 : _count(new_macro(counter(p)))
222 {
223 }
224 template <class T, class C>
225 inline
227 : _count(static_cast<counter*>(count))
228 {
229  ++(*_count);
230 }
231 template <class T, class C>
232 inline
234  : _count(sp._count)
235 {
236  ++(*_count);
237 }
238 template <class T, class C>
239 inline
241 {
242  if (_count != 0) { --(*_count); }
243 }
244 template <class T, class C>
245 inline
248 {
249  if (_count != sp._count) {
250  --(*_count);
251  _count = sp._count;
252  ++(*_count);
253  }
254  return *this;
255 }
256 template <class T, class C>
257 inline
258 const T*
260 {
261  return _count -> _p;
262 }
263 template <class T, class C>
264 inline
265 const T&
267 {
268  return *pointer();
269 }
270 template <class T, class C>
271 inline
272 const T*
274 {
275  return pointer();
276 }
277 template <class T, class C>
278 inline
279 const T&
281 {
282  return data();
283 }
284 template <class T, class C>
285 inline
286 T*
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 }
298 template <class T, class C>
299 inline
300 T*
302 {
303  return pointer();
304 }
305 template <class T, class C>
306 inline
307 T&
309 {
310  return *pointer();
311 }
312 template <class T, class C>
313 inline
314 T&
316 {
317  return data();
318 }
319 // -----------------------------------------------------------------------
320 // copy functors implementing the three possible copy semantics
321 // -----------------------------------------------------------------------
322 namespace details {
323 
324 // constructor_copy uses the copy constructor of the object - used for simple types
325 template <typename T>
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
331 template <typename T>
332 struct 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
337 template <typename T>
338 struct 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]
350 template <typename T>
351 class smart_pointer : public smart_pointer_base<T, details::constructor_copy<T> > {
354  public:
355  typedef T handled_type;
356  typedef typename base::internal internal;
357  smart_pointer (T* p = 0) : base (p) {}
358  smart_pointer (void* count, internal i) : base(count,i) {}
361  base::operator= (x); return *this; }
363 };
364 // [verbatim_smart_pointer]
365 // -----------------------------------------------------------------------
366 // smart_pointer_clone<T>
367 // -----------------------------------------------------------------------
368 // [verbatim_smart_pointer_clone]
369 template <typename T>
370 class smart_pointer_clone : public smart_pointer_base<T, details::clone_copy<T> > {
371  typedef details::clone_copy<T> C;
373  public:
374  typedef T handled_type;
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]
388 template <typename T>
389 class smart_pointer_nocopy : public smart_pointer_base<T, details::no_copy<T> > {
390  typedef details::no_copy<T> C;
392  public:
393  typedef T handled_type;
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 // -----------------------------------------------------------------------
410 using namespace rheolef;
411 using namespace std;
412 
413 // [verbatim_smart_pointer_tst]
414 // data representation (could be file "container_data.h")
415 typedef int T;
416 class 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 //
450 class container : private smart_pointer<container_data> {
451 public:
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 //
462 container::container (int n)
463 : smart_pointer<container_data> (new container_data(n))
464 {}
465 const T&
466 container::operator[] (int i) const {
467  // use read access data()
468  return data().operator[] (i);
469 }
470 T&
471 container::operator[] (int i) {
472  // use write access data() that check occurrence count
473  return data().operator [] (i);
474 }
475 // test program
476 int 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
int main(int argc, char **argv)
Definition: csr.cc:270
smart_pointer_base(void *count, internal)
const T & operator*() const
const T * pointer() 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 > &)
counter * get_count() const
smart_pointer_clone< T > & operator=(const smart_pointer_clone< T > &x)
smart_pointer_clone(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)
smart_pointer(const smart_pointer< T > &x)
smart_pointer< T > & operator=(const smart_pointer< T > &x)
#define error_macro(message)
Definition: dis_macros.h:49
Expr1::float_type T
Definition: field_expr.h:230
This file is part of Rheolef.
Definition: sphere.icc:25
T * operator()(const T &from)
T * operator()(const T &from)