summaryrefslogtreecommitdiff
path: root/lemon/doc/named-param.dox
blob: 2a981f7dc2875756765525c6f0f480c1cad0d23f (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/* -*- mode: C++; indent-tabs-mode: nil; -*-
 *
 * This file is a part of LEMON, a generic C++ optimization library.
 *
 * Copyright (C) 2003-2009
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
 *
 * Permission to use, modify and distribute this software is granted
 * provided that this copyright notice appears in all copies. For
 * precise terms see the accompanying LICENSE file.
 *
 * This software is provided "AS IS" with no warranty of any kind,
 * express or implied, and with no claim as to its suitability for any
 * purpose.
 *
 */

/*!

\page named-param Named Parameters

\section named-func-param Named Function Parameters

Several modern languages provide a convenient way to refer the
function parameters by name also when you call the function. It is
especially comfortable in case of a function having tons of parameters
with natural default values. Sadly, C++ lack this amenity.

However, with a crafty trick and with some little
inconvenience, it is possible to emulate is.
The example below shows how to do it.

\code
class namedFn
{
  int _id;
  double _val;
  int _dim;

  public:
  namedFn() : _id(0), _val(1), _dim(2) {}
  namedFn& id(int p)     { _id  = p ; return *this; }
  namedFn& val(double p) { _val = p ; return *this; }
  namedFn& dim(int p)    { _dim = p ; return *this; }

  run() {
    std::cout << "Here comes the function itself\n" <<
              << "With parameters "
              << _id << ", " << _val << ", " << _dim << std::endl;
  }
};
\endcode

Then you can use it like this.

\code
namedFn().id(3).val(2).run();
\endcode

The trick is obvious, each "named parameter" changes one component of
the underlying class, then gives back a reference to it. Finally,
<tt>run()</tt> executes the algorithm itself.

\note Although it is a class, namedFn is used pretty much like as it were
a function. That it why we called it namedFn instead of \c NamedFn.

\note In fact, the final <tt>.run()</tt> could be made unnecessary,
because the algorithm could also be implemented in the destructor of
\c namedFn instead. This however would make it impossible to implement
functions with return values, and would also cause serious problems when
implementing \ref named-templ-func-param "named template parameters".
<b>Therefore, by convention, <tt>.run()</tt> must be used
explicitly to execute a function having named parameters
everywhere in LEMON.</b>

\section named-templ-func-param Named Function Template Parameters

A named parameter can also be a template function. The usage is
exactly the same, but the implementation behind is a kind of black
magic and they are the dirtiest part of the LEMON code.

You will probably never need to know how it works, but if you really
committed, have a look at \ref lemon/graph_to_eps.h for an example.

\section traits-classes Traits Classes

A similar game can also be played when defining classes. In this case
the type of the class attributes can be changed. Initially we have to
define a special class called <em>Traits Class</em> defining the
default type of the attributes. Then the types of these attributes can
be changed in the same way as described in the next section.

See \ref lemon::DijkstraDefaultTraits for an
example how a traits class implementation looks like.

\section named-templ-param Named Class Template Parameters

If we would like to change the type of an attribute in a class that
was instantiated by using a traits class as a template parameter, and
the class contains named parameters, we do not have to instantiate again
the class with new traits class, but instead adaptor classes can
be used as shown in the following example.

\code
Dijkstra<>::SetPredMap<NullMap<Node,Arc> >::Create
\endcode

It can also be used in conjunction with other named template
parameters in arbitrary order.

\code
Dijkstra<>::SetDistMap<MyMap>::SetPredMap<NullMap<Node,Arc> >::Create
\endcode

The result will be an instantiated Dijkstra class, in which the
DistMap and the PredMap is modified.

*/