DGtal  1.5.beta
DGtal::Clone< T > Class Template Reference

Aim: This class encapsulates its parameter class to indicate that the given parameter is required to be duplicated (generally, this is done to have a longer lifetime than the function itself). On one hand, the user is reminded of the possible cost of duplicating the argument parameter, while he is also aware that the lifetime of the parameter is not a problem for the function. On the other hand, the Clone class is smart enough to enforce duplication only if needed. Substantial speed-up can be achieve through this mechanism. More...

#include <DGtal/base/Clone.h>

Data Structures

struct  TempPtr
 Internal class that is used for a late deletion of an acquired pointer. More...
 

Public Member Functions

 ~Clone ()
 
 Clone (const Clone &other)
 
 Clone (const T &t)
 
 Clone (T *ptrT)
 
 Clone (const CowPtr< T > &ptrT)
 
 Clone (const CountedPtr< T > &ptrT)
 
 Clone (T &&t)
 
 operator T () const
 
 operator CowPtr< T > () const
 
 operator CountedPtr< T > () const
 
T * operator& () const
 

Protected Types

enum  Parameter {
  CONST_LEFT_VALUE_REF , LEFT_VALUE_REF , PTR , CONST_PTR ,
  COW_PTR , COUNTED_PTR , RIGHT_VALUE_REF , COUNTED_PTR_OR_PTR ,
  COUNTED_CONST_PTR_OR_CONST_PTR
}
 Internal class that allows to distinguish the different types of parameters. More...
 

Protected Member Functions

void display (const std::string &method, Parameter p) const
 

Private Member Functions

 Clone ()
 
Cloneoperator= (const Clone &other)
 

Private Attributes

const Parameter myParam
 Characterizes the type of the input parameter at clone instanciation. More...
 
const void *const myPtr
 Stores the address of the input parameter for further use. More...
 

Detailed Description

template<typename T>
class DGtal::Clone< T >

Aim: This class encapsulates its parameter class to indicate that the given parameter is required to be duplicated (generally, this is done to have a longer lifetime than the function itself). On one hand, the user is reminded of the possible cost of duplicating the argument parameter, while he is also aware that the lifetime of the parameter is not a problem for the function. On the other hand, the Clone class is smart enough to enforce duplication only if needed. Substantial speed-up can be achieve through this mechanism.

Description of template class 'Clone'

(For a complete description, see Parameter passing, cloning and referencing).

The class Clone is used in methods or functions to encapsulate the parameter types. The following conversion from input parameter to data member or variable are sumed up in the following table:

Argument type: const T& T* CountedPtr<T> CowPtr<T> T&& (c++11)
To:T Dupl. O(N) Acq. Dupl. O(N) Dupl. O(N) Dupl. O(N) Move. O(1)
To:T* Dupl. O(N) Acq. O(1) Dupl. O(N) Dupl. O(N) Move. O(1)
To:CowPtr<T> Dupl. O(N) Acq. O(1) Lazy. O(1)/O(N) Lazy. O(1)/O(N) Move. O(1)

with abbreviations:

  • Dupl. Object is duplicated.
  • Lazy. Object is lazily duplicated, meaning only when the user writes on it (which may be never).
  • Acq. Dynamically allocated pointer is acquired. User should take care himself of deletion only if storing the parameter with a pointer.
  • Move. The object is moved into the new object. This is generally much faster than copy. This is true for instance for all classical STL containers. You can also write a specific move constructor for your class.

It is clear that worst case is duplication while sometimes Clone is constant time (while guaranteeing object invariance and life-time).

Note
The usage of Clone<T> instead of const T & or const T * in parameters is always recommended when the user duplicates the parameter and stores a clone of it as a data member for later use. The usage Clone<T> instead of T is recommended whenever T is big (the object is sometimes duplicated twice). When the object is small, writing either Clone<T> or T is acceptable. If your member is a CowPtr<T>, then you should use a Clone<T> as parameter. Depending on your data member, we advise the following parameter definition when duplication is asked for.
member type: T big T CowPtr<T> T*
parameter T or Clone<T> Clone<T> Clone<T> Clone<T>
Note
A conversion to T* means pointer acquisition. Hence the programmer should take care of deletion of the object. Otherwise, deletion is automatic for T or CowPtr<T> member. Furthermore, a conversion to a T* requires the use of the address operator (operator&) by the developer. If argument is Clone<T> a, and member name is b:
member type: T T* CowPtr<T>
member deletion: automatic manual automatic
conversion: automatic: b(a) address: b(&a) automatic: b(a)
Note
When choosing a Clone<T> parameter, the programmer should really consider using a CowPtr<T> member to store it, since it is the most versatile and optimizable variant. The only advantage of the two others storing methods (T and T*) is that there is one less indirection.
Note that an instance of Clone<T> is itself a light object (it holds only a const enum and const pointer), the duplication (if necessary) takes place when the user instantiates its member of type T (or CowPtr<T> or T* member).
Template Parameters
Tis any type.
See also
Alias
ConstAlias
Note
(Speed) Even on a small type (here a pair<int,int>), it is much faster than NClone and has the advantage (wrt Clone<T>) to handle nicely both const T& and CowPtr<T> as input. It may be slightly slower than deprecated::Clone (and by value or by const ref parameter passing) for small objects like a pair<int,int>. This is certainly due to the fact that it uses one more integer register for myParam data member.
Type Context value const ref deprecated::Clone Clone
2xint i7 2.4GHz 48ms 48ms 48ms 59ms
2xdouble i7 2.4GHz 48ms 48ms 48ms 49ms
2xint Xeon 2.67GHz 54ms 54ms 54ms 54ms
2xdouble Xeon 2.67GHz 54ms 54ms 54ms 53.5ms
Note
It prevents direct assignment to CountedPtr<T> since their meaning is "shared_ptr".

It can be used as follows. Consider this simple example where class A is a big object. Then we define three classes B1, B2 and B3, that uses some instance of A.

const int N = 10000;
struct A { ...
int table[N];
};
// Each B1, B2 or B3 uses A, but we do not know if A will be copied
// or just referenced by only looking at the declaration of
// the method. Generally the ambiguity is removed by adding
// comments or, for the experienced developper, by looking at
// other parts of the code.
// Only aliasing, but for a long lifetime.
struct B1 {
B1( const A & a ) // ambiguous, cost is O(1) here and lifetime of a should exceed constructor.
: myA( a ) {}
...
const A & myA;
};
// Copying as data member (stack or heap depending on B2 instance)
struct B2 {
B2( const A & a ) // ambiguous, cost is O(N) here
: myA( a ) {}
...
A myA;
};
// Copying on heap and data member pointing on it.
struct B3 {
B3( const A & a ) // ambiguous, cost is O(N) here
{ myA = new A( a ); }
~B3()
{ if ( myA != 0 ) delete myA; }
...
A* myA;
};

Sometimes it is also very important that the developper that uses the library is conscious that an object, say b, may require that an instance a given as parameter should have a lifetime longer than b itself (case for an instance of B1 above). Classes Clone, Alias, ConstAlias exist for these reasons. The classes above may be rewritten as follows.

// Aliasing for a long lifetime is visible.
struct B1 {
B1( ConstAlias<A> a ) // not ambiguous, cost is O(1) here and lifetime of a should be long enough
: myA( a ) {}
...
const A & myA;
// or Const A* myA;
};
// Cloning as data member is visible.
struct B2 {
B2( Clone<A> a ) // not ambiguous, cost is O(N) here and lifetime of a is whatever.
: myA( a ) {}
...
A myA;
};
// Cloning on the heap requires address operator, so that the user remembers calling \c delete.
struct B3_v1 {
B3_v1( Clone<A> a ) // not ambiguous, cost is O(N) here and lifetime of a is whatever.
: myA( &a ) {}
~B3_v1() { if ( myA != 0 ) delete myA; }
...
A* myA;
};
// Cloning on the heap with CountedPtr mechanism is straightforward.
struct B3_v2 {
B3_v2( Clone<A> a ) // not ambiguous, cost is O(N) here and lifetime of a is whatever.
: myA( a ) {}
~B3_v2() {} // CountedPtr takes care of delete.
...
CountedPtr<A> myA;
};
// Cloning on the heap with CowPtr mechanism is straightforward.
struct B3_v3 {
B3_v3( Clone<A> a ) // not ambiguous, cost is O(N) here and lifetime of a is whatever.
: myA( a ) {}
~B3_v3() {} // CountedPtr takes care of delete.
...
CowPtr<A> myA;
};
...
A a1;
B1 b( a1 ); // do not duplicate a1
B2 bb( a1 ); // duplicate a1
B2 bbb( &a1 ); // also duplicate a1 !
B3_v1 c1( a1 ); // duplicate a1 on the heap
B3_v2 c1( a1 ); // duplicate a1 on the heap
B3_v3 c1( a1 ); // duplicate a1 on the heap

A last question could be why are we not just passing the instance of A by value. This, for sure, would tell the developper that the instance is duplicated somehow. The problem is that it induces generally two duplications, and not only one ! It may be possible that the compiler optimizes things nicely but it is unclear if the compiler will always do it. Furthermore, sometimes, no duplication is needed (when duplicating a CowPtr for instance).

struct B4 {
B4( A a ) // not ambiguous, but cost is O(2N) here.
: myA( a ) {}
...
A myA;
};
A a1;
B4 b4( a1 ) // The object \a a1 is copied once on the heap as the parameter \a a, and once as the member \a b3.myA.
Note
The user should not used Clone<T> for data members, only as a type for parameters.

Definition at line 266 of file Clone.h.

Member Enumeration Documentation

◆ Parameter

template<typename T >
enum DGtal::Clone::Parameter
protected

Internal class that allows to distinguish the different types of parameters.

Enumerator
CONST_LEFT_VALUE_REF 
LEFT_VALUE_REF 
PTR 
CONST_PTR 
COW_PTR 
COUNTED_PTR 
RIGHT_VALUE_REF 
COUNTED_PTR_OR_PTR 
COUNTED_CONST_PTR_OR_CONST_PTR 

Definition at line 272 of file Clone.h.

Constructor & Destructor Documentation

◆ ~Clone()

template<typename T >
DGtal::Clone< T >::~Clone ( )
inline

Destructor. Does nothing.

Definition at line 320 of file Clone.h.

320 {}

◆ Clone() [1/7]

template<typename T >
DGtal::Clone< T >::Clone ( const Clone< T > &  other)
inline

Copy constructor. The cloning is just forwarded.

Parameters
otherthe clone object to clone

Definition at line 326 of file Clone.h.

327  : myParam( other.myParam ), myPtr( other.myPtr ) {}
const Parameter myParam
Characterizes the type of the input parameter at clone instanciation.
Definition: Clone.h:498
const void *const myPtr
Stores the address of the input parameter for further use.
Definition: Clone.h:500

◆ Clone() [2/7]

template<typename T >
DGtal::Clone< T >::Clone ( const T &  t)
inline

Constructor from an instance of T. The object is pointed in 'this'. It is duplicated (or not) when the user claims it.

Parameters
tany object of type T.

Definition at line 334 of file Clone.h.

335  : myParam( CONST_LEFT_VALUE_REF ), myPtr( static_cast<const void*>( &t ) ) {}

◆ Clone() [3/7]

template<typename T >
DGtal::Clone< T >::Clone ( T *  ptrT)
inline

Constructor from a pointer to a valid instance of T. The object is pointed in 'this'. It is duplicated (or not) when the user claims it.

Parameters
ptrTany valid pointer to a object of type T.
Precondition
ptrT != 0

Definition at line 343 of file Clone.h.

344  : myParam( PTR ), myPtr( static_cast<const void*>( ptrT ) ) {}

◆ Clone() [4/7]

template<typename T >
DGtal::Clone< T >::Clone ( const CowPtr< T > &  ptrT)
inline

Constructor from CowPtr<T>. The object is pointed in 'this'. It is duplicated (or not) when the user claims it.

Parameters
ptrTany copy-on-write pointer to a object of type T.

Definition at line 352 of file Clone.h.

353  : myParam( COW_PTR ), myPtr( static_cast<const void*>( &ptrT ) ) {}

◆ Clone() [5/7]

template<typename T >
DGtal::Clone< T >::Clone ( const CountedPtr< T > &  ptrT)
inline

Constructor from CountedPtr<T>. The object is pointed in 'this'. It is duplicated (or not) when the user claims it.

Parameters
ptrTany shared pointer to a object of type T.

Definition at line 361 of file Clone.h.

362  : myParam( COUNTED_PTR ), myPtr( static_cast<const void*>( &ptrT ) ) {}

◆ Clone() [6/7]

template<typename T >
DGtal::Clone< T >::Clone ( T &&  t)
inline

Constructor from right-reference value. The object is pointed in 'this'. It is duplicated (or not) when the user claims it.

Parameters
tany shared pointer to a object of type T.

Definition at line 370 of file Clone.h.

371  : myParam( RIGHT_VALUE_REF ), myPtr( static_cast<const void*>( &t ) ) {}

◆ Clone() [7/7]

template<typename T >
DGtal::Clone< T >::Clone ( )
private

Constructor. Forbidden.

Member Function Documentation

◆ display()

template<typename T >
void DGtal::Clone< T >::display ( const std::string &  method,
Parameter  p 
) const
inlineprotected

Debug method for displaying what's happening when using Clone mechanism

Parameters
methodthe name of the conversion method
pthe type of parameter

Definition at line 280 of file Clone.h.

281  {
282  std::string sp;
283  switch (p) {
284  case CONST_LEFT_VALUE_REF: sp = "CONST_LEFT_VALUE_REF"; break;
285  case LEFT_VALUE_REF: sp = "LEFT_VALUE_REF"; break;
286  case PTR: sp = "PTR"; break;
287  case CONST_PTR: sp = "CONST_PTR"; break;
288  case COW_PTR: sp = "COW_PTR"; break;
289  case COUNTED_PTR: sp = "COUNTED_PTR"; break;
290  case RIGHT_VALUE_REF: sp = "RIGHT_VALUE_REF"; break;
291  case COUNTED_PTR_OR_PTR: sp = "COUNTED_PTR_OR_PTR"; break;
292  case COUNTED_CONST_PTR_OR_CONST_PTR: sp = "COUNTED_CONST_PTR_OR_CONST_PTR"; break;
293  default: sp = "UNKNOWN"; break;
294  }
295  trace.info() << "[Clone<T>::" << method << " param="
296  << sp << "]" << std::endl;
297 
298  }
std::ostream & info()
Trace trace
Definition: Common.h:153

References DGtal::Clone< T >::CONST_LEFT_VALUE_REF, DGtal::Clone< T >::CONST_PTR, DGtal::Clone< T >::COUNTED_CONST_PTR_OR_CONST_PTR, DGtal::Clone< T >::COUNTED_PTR, DGtal::Clone< T >::COUNTED_PTR_OR_PTR, DGtal::Clone< T >::COW_PTR, DGtal::Trace::info(), DGtal::Clone< T >::LEFT_VALUE_REF, DGtal::Clone< T >::PTR, DGtal::Clone< T >::RIGHT_VALUE_REF, and DGtal::trace.

◆ operator CountedPtr< T >()

template<typename T >
DGtal::Clone< T >::operator CountedPtr< T > ( ) const
inline

Cast operator to a smart pointer on T instance. The object is duplicated or not depending on the type of input parameter.

  • const T & -> CountedPtr<T> // immediate duplication
  • T* -> CountedPtr<T> // acquired
  • CountedPtr<T> -> CountedPtr<T> // lazy duplication
  • CowPtr<T> -> CountedPtr<T> // immediate duplication
  • T&& -> CountedPtr<T> // move into member

Definition at line 444 of file Clone.h.

445  {
446  // display( "operator CountedPtr<T>() const", myParam );
447  switch( myParam ) {
449  return CountedPtr<T>( new T( * static_cast< const T* >( myPtr ) ) );
450  case PTR:
451  return CountedPtr<T>( const_cast<T*>( static_cast< const T* >( myPtr ) ) );
452  case COW_PTR:
453  return CountedPtr<T>( new T( * static_cast< const CowPtr<T>* >( myPtr )->get() ) );
454  case COUNTED_PTR:
455  return CountedPtr<T>( * static_cast< const CountedPtr<T>* >( myPtr ) );
456  case RIGHT_VALUE_REF:
457  return CountedPtr<T>( new T( std::move( * const_cast<T*>( static_cast< const T* >( myPtr ) ) ) ) );
458  default: ASSERT( false && "[Clone::operator CountedPtr<T>() const] Invalid cast for given type. " );
459  return CountedPtr<T>( 0 );
460  }
461  }

References DGtal::Clone< T >::CONST_LEFT_VALUE_REF, DGtal::Clone< T >::COUNTED_PTR, DGtal::Clone< T >::COW_PTR, DGtal::Clone< T >::myParam, DGtal::Clone< T >::myPtr, DGtal::Clone< T >::PTR, and DGtal::Clone< T >::RIGHT_VALUE_REF.

◆ operator CowPtr< T >()

template<typename T >
DGtal::Clone< T >::operator CowPtr< T > ( ) const
inline

Cast operator to a copy-on-write pointer on T instance. The object is duplicated or not depending on the type of input parameter.

  • const T & -> CowPtr<T> // immediate duplication (checked)
  • T* -> CowPtr<T> // acquired (checked)
  • CountedPtr<T> -> CowPtr<T> // lazy duplication (checked)
  • CowPtr<T> -> CowPtr<T> // lazy duplication (checked)
  • T&& -> CowPtr<T> // move into member (checked)

Definition at line 415 of file Clone.h.

416  {
417  // display( "operator CowPtr<T>() const", myParam );
418  switch( myParam ) {
420  return CowPtr<T>( new T( * static_cast< const T* >( myPtr ) ) );
421  case PTR:
422  return CowPtr<T>( const_cast<T*>( static_cast< const T* >( myPtr ) ) );
423  case COW_PTR:
424  return CowPtr<T>( * static_cast< const CowPtr<T>* >( myPtr ) );
425  case COUNTED_PTR:
426  return CowPtr<T>( * static_cast< const CountedPtr<T>* >( myPtr ), true );
427  case RIGHT_VALUE_REF:
428  return CowPtr<T>( new T( std::move( * const_cast<T*>( static_cast< const T* >( myPtr ) ) ) ) );
429  default: ASSERT( false && "[Clone::operator CowPtr<T>() const] Invalid cast for given type. " );
430  return CowPtr<T>( 0 );
431  }
432  }

References DGtal::Clone< T >::CONST_LEFT_VALUE_REF, DGtal::Clone< T >::COUNTED_PTR, DGtal::Clone< T >::COW_PTR, DGtal::Clone< T >::myParam, DGtal::Clone< T >::myPtr, DGtal::Clone< T >::PTR, and DGtal::Clone< T >::RIGHT_VALUE_REF.

◆ operator T()

template<typename T >
DGtal::Clone< T >::operator T ( ) const
inline

Cast operator to a T instance. The object is duplicated or not depending on the type of input parameter.

  • const T & -> T // immediate duplication (checked)
  • T* -> T // immediate duplication, acquired and deleted. (checked)
  • CountedPtr<T> -> T // immediate duplication (checked)
  • CowPtr<T> -> T // immediate duplication (checked)
  • T&& -> T // move into member (checked)

Definition at line 384 of file Clone.h.

385  {
386  // display( "operator T() const", myParam );
387  switch( myParam ) {
389  return T( * static_cast< const T* >( myPtr ) );
390  case PTR: {
391  TempPtr tmp( const_cast< T* >( static_cast< const T* >( myPtr ) ) );
392  return T( * static_cast< const T* >( myPtr ) );
393  } // destroy acquired pointer.
394  case COW_PTR:
395  return T( * static_cast< const CowPtr<T>* >( myPtr )->get() );
396  case COUNTED_PTR:
397  return T( * static_cast< const CountedPtr<T>* >( myPtr )->get() );
398  case RIGHT_VALUE_REF:
399  return T( std::move( * const_cast<T*>( static_cast< const T* >( myPtr ) ) ) );
400  default: ASSERT( false && "[Clone::operator T() const] Invalid cast for given type. " );
401  return T( * static_cast< const T* >( myPtr ) );
402  }
403  }

References DGtal::Clone< T >::CONST_LEFT_VALUE_REF, DGtal::Clone< T >::COUNTED_PTR, DGtal::Clone< T >::COW_PTR, DGtal::Clone< T >::myParam, DGtal::Clone< T >::myPtr, DGtal::Clone< T >::PTR, and DGtal::Clone< T >::RIGHT_VALUE_REF.

◆ operator&()

template<typename T >
T* DGtal::Clone< T >::operator& ( ) const
inline

Address operator that returns the address of the given T instance. The object is duplicated or not depending on the type of input parameter.

Returns
a pointer on an instance of T.
  • const T & -> T* // immediate duplication, should be deleted at the end. (checked)
  • CowPtr<T> -> T* // immediate duplication, should be deleted at the end. (checked)
  • CountedPtr<T> -> T* // immediate duplication, should be deleted at the end. (checked)
  • T* -> T* // acquired, should be deleted at the end. (checked)
  • T&& -> T* // move into member, should be deleted at the end. (checked)

Definition at line 476 of file Clone.h.

477  {
478  // display( "T* operator &() const", myParam );
479  switch( myParam ) {
481  return new T( * static_cast< const T* >( myPtr ) );
482  case PTR:
483  return const_cast<T*>( static_cast< const T* >( myPtr ) );
484  case COW_PTR:
485  return new T( *( static_cast< const CowPtr<T>* >( myPtr )->get() ) );
486  case COUNTED_PTR:
487  return new T( *( static_cast< const CountedPtr<T>* >( myPtr )->get() ) );
488  case RIGHT_VALUE_REF:
489  return new T( std::move( * const_cast<T*>( static_cast< const T* >( myPtr ) ) ) );
490  default: ASSERT( false && "[T* Clone::operator&() const] Invalid address for given type. " );
491  return 0;
492  }
493  }

References DGtal::Clone< T >::CONST_LEFT_VALUE_REF, DGtal::Clone< T >::COUNTED_PTR, DGtal::Clone< T >::COW_PTR, DGtal::Clone< T >::myParam, DGtal::Clone< T >::myPtr, DGtal::Clone< T >::PTR, and DGtal::Clone< T >::RIGHT_VALUE_REF.

◆ operator=()

template<typename T >
Clone& DGtal::Clone< T >::operator= ( const Clone< T > &  other)
private

Assignment.

Parameters
otherthe object to copy.
Returns
a reference on 'this'. Forbidden (otherwise the user might be tempted to use it as a member).

Field Documentation

◆ myParam

template<typename T >
const Parameter DGtal::Clone< T >::myParam
private

Characterizes the type of the input parameter at clone instanciation.

Definition at line 498 of file Clone.h.

Referenced by DGtal::Clone< T >::operator CountedPtr< T >(), DGtal::Clone< T >::operator CowPtr< T >(), DGtal::Clone< T >::operator T(), and DGtal::Clone< T >::operator&().

◆ myPtr

template<typename T >
const void* const DGtal::Clone< T >::myPtr
private

Stores the address of the input parameter for further use.

Definition at line 500 of file Clone.h.

Referenced by DGtal::Clone< T >::operator CountedPtr< T >(), DGtal::Clone< T >::operator CowPtr< T >(), DGtal::Clone< T >::operator T(), and DGtal::Clone< T >::operator&().


The documentation for this class was generated from the following file: