4 \page adaptor-references Smart Reference Handling
6 The adaptor classes are very useful tools in the lemon library. It makes
7 possible to create various data view of the current data structures without
8 of the copy of them. This makes the lemon programming efficient and
11 \section problem The problem
13 The adaptors usually use references or pointers to reference to an
14 existing data structure. We may use an algorithm in the next way:
16 function_algorithm(adaptor(structure));
19 But what about the class algorithms:
22 alg.add(adaptor(structure));
25 The algorithm store a reference to the given structure. It is a created
26 as temporarly and when the expression of the \c add() function is evaluated it
27 will be destructed. It is very dangerous handling of the adaptors.
29 \section solution The solution
31 We made reference to a temporarly constructed adaptor but we should make
32 a copy of the adaptor when it is given as parameter to a class.
33 It is not impossible with a little tranformation of the code.
35 Let's first create some helper class:
37 template <typename _Type, typename Enable = void>
38 struct SmartConstReference {
39 typedef const _Type& Type;
42 template <typename _Type>
43 struct SmartConstReference<
45 typename enable_if<typename _Type::NeedCopy, void>::type
47 typedef const _Type Type;
50 Then we can place NeedCopy tags in the adaptor classes:
52 template<class M1,class M2>
54 typename SmartConstReference<M1>::Type m1;
55 typename SmartConstReference<M2>::Type m2;
59 typedef True NeedCopy;
61 typedef typename M1::Key Key;
62 typedef typename M1::Value Value;
64 AddMap(const M1 &_m1,const M2 &_m2) : m1(_m1), m2(_m2) {};
65 Value operator[](Key k) const {return m1[k]+m2[k];}
68 Then we can transform all of the template map and graph references to
69 \c SmartConstReference<Map>::Type or \c SmartConstReference<Graph>::Type.
70 This way we copy all of maps and graphs what we should copy but the
71 greater data structures are not copied.
73 \section not-const If the adaptor is not const
74 The solution is very similar but it gives an additional problem.
75 We make the same \c SmartReferences:
77 template <typename _Type, typename Enable = void>
78 struct SmartReference {
82 template <typename _Type>
83 struct SmartReference<
85 typename enable_if<typename _Type::NeedCopy, void>::type
90 Let's create a class that use it:
92 template <typename Map>
95 SmartReference<Map>::Type map;
96 Algorithm(Map& _map) : map(_map) {}
100 But if we want to give an adaptor function as parameter
101 it will be a compile error. The adaptor will be created as temporarly
102 so it cannot give as reference just as const reference.
104 Make more helper class:
106 template <typename _Type, typename Enable = void>
107 struct SmartParameter {
111 template <typename _Type>
112 struct SmartParameter<
114 typename enable_if<typename _Type::NeedCopy, void>::type
116 typedef const _Type& Type;
119 And the repaired code:
121 template <typename Map>
124 SmartReference<Map>::Type map;
125 Algorithm(SmartParameter<Map>::Type _map) : map(_map) {}
129 But some times it does not help:
135 template <typename Map>
136 void addMap(SmartParameter<Map>::Type _map) {
142 Actually, it is a good code but the template parameter should
143 be written because it cannot be found out from the parameter type.
144 This can be solved with a bigger transformation:
150 template <typename Map>
151 void addMap(const Map& _map) {
152 _addMap<SmartParameter<Map>::Type, Map>(_map);
154 template <typename Map>
155 void addMap(const Map& _map) {
156 _addMap<SmartParameter<Map>::Type, Map>(_map);
160 template <typename MapParameter, typename Map>
161 void _addMap(MapParameter _map) {
167 This way we solved the smart referencing problem.