# HG changeset patch # User deba # Date 1116091931 0 # Node ID afaa773d0ad0029ea90eb71510319bbf436b3c41 # Parent 53c2a0ccc9a4e940147e9344a135caf068fb0e57 Handling smarter the references It's used by the lemon IO and proposed by the adaptors. diff -r 53c2a0ccc9a4 -r afaa773d0ad0 doc/adaptor_references.dox --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/adaptor_references.dox Sat May 14 17:32:11 2005 +0000 @@ -0,0 +1,170 @@ +namespace lemon { +/*! + +\page adaptor-references 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. + +\section problem The problem + +The adaptors usually use references or pointers to reference to an +existing data structure. We may use an algorithm in the next way: +\code +function_algorithm(adaptor(structure)); +\endcode + +But what about the class algorithms: +\code +class_algorithm alg; +alg.add(adaptor(structure)); +alg.run(); +\endcode +The algorithm store a reference to the given structure. It is a created +as temporarly and when the expression of the \c add() function is evaluated it +will be destructed. It is very dangerous handling of the adaptors. + +\section solution 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: +\code +template +struct SmartConstReference { + typedef const _Type& Type; +}; + +template +struct SmartConstReference< + _Type, + typename enable_if::type +> { + typedef const _Type Type; +}; +\endcode +Then we can place NeedCopy tags in the adaptor classes: +\code +template +class AddMap { + typename SmartConstReference::Type m1; + typename SmartConstReference::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];} +}; +\endcode +Then we can transform all of the template map and graph references to +\c SmartConstReference::Type or \c SmartConstReference::Type. +This way we copy all of maps and graphs what we should copy but the +greater data structures are not copied. + +\section not-const If the adaptor is not const +The solution is very similar but it gives an additional problem. +We make the same \c SmartReferences: +\code +template +struct SmartReference { + typedef _Type& Type; +}; + +template +struct SmartReference< + _Type, + typename enable_if::type +> { + typedef _Type Type; +}; +\endcode +Let's create a class that use it: +\code +template +class Algorithm { +public: + SmartReference::Type map; + Algorithm(Map& _map) : map(_map) {} + ... +}; +\endcode +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: +\code +template +struct SmartParameter { + typedef _Type& Type; +}; + +template +struct SmartParameter< + _Type, + typename enable_if::type +> { + typedef const _Type& Type; +}; +\endcode +And the repaired code: +\code +template +class Algorithm { +public: + SmartReference::Type map; + Algorithm(SmartParameter::Type _map) : map(_map) {} + ... +}; +\endcode +But some times it does not help: +\code +class Algorithm { +public: + ... + + template + void addMap(SmartParameter::Type _map) { + ... + } + ... +}; +\endcode +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: +\code +class Algorithm { +public: + ... + + template + void addMap(const Map& _map) { + _addMap::Type, Map>(_map); + } + template + void addMap(const Map& _map) { + _addMap::Type, Map>(_map); + } + +private: + template + void _addMap(MapParameter _map) { + ... + } + ... +}; +\endcode +This way we solved the smart referencing problem. +\author Balazs Dezso +*/ +} diff -r 53c2a0ccc9a4 -r afaa773d0ad0 src/lemon/utility.h --- a/src/lemon/utility.h Sat May 14 17:29:28 2005 +0000 +++ b/src/lemon/utility.h Sat May 14 17:32:11 2005 +0000 @@ -107,6 +107,47 @@ template struct lazy_disable_if : public lazy_disable_if_c {}; + // smart referencing + + template + struct SmartReference { + typedef _Type& Type; + }; + + template + struct SmartReference< + _Type, + typename enable_if::type + > { + typedef _Type Type; + }; + + template + struct SmartConstReference { + typedef const _Type& Type; + }; + + template + struct SmartConstReference< + _Type, + typename enable_if::type + > { + typedef const _Type Type; + }; + + template + struct SmartParameter { + typedef _Type& Type; + }; + + template + struct SmartParameter< + _Type, + typename enable_if::type + > { + typedef const _Type& Type; + }; + } // namespace lemon #endif