Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Smart Reference Handling

The adaptor classes are very useful tools in the lemon library. It makes possible to create various data view of the current data structures without of the copy of them. This makes the lemon programming efficient and consederably fast.

The problem

The adaptors usually use references or pointers to reference to an existing data structure. We may use an algorithm in the following way:
function_algorithm(adaptor(structure));

But what about the class algorithms:

class_algorithm alg;
alg.add(adaptor(structure));
alg.run();
The algorithm store a reference to the given structure. It is a created as temporarly and when the expression of the add() function is evaluated it will be destructed. It is very dangerous handling of the adaptors.

The solution

We made reference to a temporarly constructed adaptor but we should make a copy of the adaptor when it is given as parameter to a class. It is not impossible with a little tranformation of the code.

Let's first create some helper class:

template <typename _Type, typename Enable = void>
struct SmartConstReference {
  typedef const _Type& Type;
};
  
template <typename _Type>
struct SmartConstReference<
  _Type, 
  typename enable_if<typename _Type::NeedCopy, void>::type
> {
  typedef const _Type Type;
};
Then we can place NeedCopy tags in the adaptor classes:
template<class M1,class M2> 
class AddMap {
  typename SmartConstReference<M1>::Type m1;
  typename SmartConstReference<M2>::Type m2;

public:

  typedef True NeedCopy;

  typedef typename M1::Key Key;
  typedef typename M1::Value Value;

  AddMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {};
  Value operator[](Key k) const {return m1[k]+m2[k];}
};
Then we can transform all of the template map and graph references to SmartConstReference<Map>::Type or SmartConstReference<Graph>::Type. This way we copy all of maps and graphs what we should copy but the greater data structures are not copied.

If the adaptor is not const

The solution is very similar but it gives an additional problem. We make the same SmartReferences:
template <typename _Type, typename Enable = void>
struct SmartReference {
  typedef _Type& Type;
};

template <typename _Type>
struct SmartReference<
  _Type, 
  typename enable_if<typename _Type::NeedCopy, void>::type
> {
  typedef _Type Type;
};
Let's create a class that use it:
template <typename Map>
class Algorithm {
public:
  SmartReference<Map>::Type map;
  Algorithm(Map& _map) : map(_map) {}
  ...
};
But if we want to give an adaptor function as parameter it will be a compile error. The adaptor will be created as temporarly so it cannot give as reference just as const reference.

Make more helper class:

template <typename _Type, typename Enable = void>
struct SmartParameter {
  typedef _Type& Type;
};

template <typename _Type>
struct SmartParameter<
  _Type, 
  typename enable_if<typename _Type::NeedCopy, void>::type
> {
  typedef const _Type& Type;
};
And the repaired code:
template <typename Map>
class Algorithm {
public:
  SmartReference<Map>::Type map;
  Algorithm(SmartParameter<Map>::Type _map) : map(_map) {}
  ...
};
But some times it does not help:
class Algorithm {
public:
  ...

  template <typename Map>
  void addMap(SmartParameter<Map>::Type _map) {
    ...
  }
  ...
};
Actually, it is a good code but the template parameter should be written because it cannot be found out from the parameter type. This can be solved with a bigger transformation:
class Algorithm {
public:
  ...

  template <typename Map>
  void addMap(const Map& _map) {
    _addMap<SmartParameter<Map>::Type, Map>(_map);
  }
  template <typename Map>
  void addMap(const Map& _map) {
    _addMap<SmartParameter<Map>::Type, Map>(_map);
  }

private:
  template <typename MapParameter, typename Map>
  void _addMap(MapParameter _map) {
    ...
  }
  ...
};
This way we solved the smart referencing problem.
Author:
Balazs Dezso

Generated on Sat Aug 27 14:14:56 2005 for LEMON by  doxygen 1.4.4