author Alpar Juttner Sun, 21 Sep 2008 07:49:57 +0100 changeset 268 986d30f5c1c0 parent 267 1eb606fe5591 child 269 f5965bbf1353
Improvements in named-param.dox
 doc/named-param.dox file | annotate | diff | comparison | revisions
     1.1 --- a/doc/named-param.dox	Sun Sep 21 06:13:05 2008 +0100
1.2 +++ b/doc/named-param.dox	Sun Sep 21 07:49:57 2008 +0100
1.3 @@ -22,21 +22,14 @@
1.4
1.5  \section named-func-param Named Function Parameters
1.6
1.7 -C++ makes it possible to use default parameter values when calling a
1.8 -function. In such a case we do not have to give value for parameters,
1.9 -the program will use the default ones.  Unfortunately sometimes this
1.10 -is not enough. If we do not want to give values for all the
1.11 -parameters, only for some of them we come across problems, because an
1.12 -arbitrary set of parameters cannot be omitted. On the other hand
1.13 -parameters have a fixed order in the head of the function.  C++ can
1.14 -apply the default values only in the back of the order, if we do not
1.15 -give other value for them.  So we can not give the function for
1.16 -example the value of the first, and the third parameter, expecting
1.17 -that the program will aplly the default value for the second
1.18 -parameter.  However sometimes we would like to use some functinos
1.19 -exactly in this way. With a crafty trick and with some little
1.20 -inconvenience this is possible. We have implemented this little trick
1.21 -as an example below.
1.22 +Several modern languages provide a convenient way to refer the
1.23 +function parameters by name also when you call the function. It is
1.24 +especially comfortable in case of a function having tons of parameters
1.25 +with natural default values. Sadly, C++ lack this amenity.
1.26 +
1.27 +However, with a crafty trick and with some little
1.28 +inconvenience, it is possible to emulate is.
1.29 +The example below shows how to do it.
1.30
1.31  \code
1.32  class namedFn
1.33 @@ -52,63 +45,62 @@
1.34    namedFn& dim(int p)    { _dim = p ; return *this; }
1.35
1.36    run() {
1.37 -    printf("Here is the function itself.");
1.38 +  std::cout << "Here comes the function itself\n" <<
1.39 +            << "With parameters "
1.40 +            << _id << ", " << _val << ", " << _dim << std::endl;
1.41    }
1.42  };
1.43  \endcode
1.44
1.45 +Then you can use it like this.
1.46
1.47 -The usage is the following.
1.48 -
1.49 -We have to define a class, let's call it \c namedFn.  Let us assume that
1.50 -we would like to use a parameter, called \c X. In the \c namedFn class we
1.51 -have to define an \c _X attribute, and a function \c X. The function
1.52 -expects a parameter with the type of \c _X, and sets the value of
1.53 -\c _X. After setting the value the function returns the class itself. The
1.54 -class also have to have a function, called for example <tt>run()</tt>, we have
1.55 -to implement here the original function itself. The constructor of the
1.56 -class have to give all the attributes like \c _X the default values of
1.57 -them.
1.58 -
1.59 -If we instantiate this class, the default values will be set for the
1.60 -attributes (originally the parameters), initially. If we call function
1.61 -\c X, we get a class with the modified parameter value of
1.62 -\c X. Therefore we can modify any parameter-value, independently from the
1.63 -order. To run the algorithm we have to call the <tt>run()</tt> function at the
1.64 -end of the row.
1.65 -
1.66 -Example:
1.67  \code
1.68  namedFn().id(3).val(2).run();
1.69  \endcode
1.70
1.71 +The trick is obvious, each "named parameter" changes one component of
1.72 +the underlying class, then gives back a reference to it. Finally,
1.73 +<tt>run()</tt> executes the algorithm itself.
1.74 +
1.75  \note Although it is a class, namedFn is used pretty much like as it were
1.76 -a function. That it why it is called namedFn and not \c NamedFn.
1.77 +a function. That it why we called it namedFn instead of \c NamedFn.
1.78
1.79 -\note In fact, the final <tt>.run()</tt> could be made unnecessary if the
1.80 -actual function code were put in the destructor instead. This however would make
1.81 -hard to implement functions with return values, and would also make the
1.82 -implementation of \ref named-templ-func-param "named template parameters"
1.83 -very problematic. <b>Therefore, by convention, <tt>.run()</tt> must be used
1.84 -to explicitly execute function having named parameters in Lemon.</b>
1.85 +\note In fact, the final <tt>.run()</tt> could be made unnecessary,
1.86 +because the algorithm could also be implemented in the destructor of
1.87 +\c namedFn instead. This however would make it impossible to implement
1.88 +functions with return values, and would also cause serious problems when
1.89 +implementing \ref named-templ-func-param "named template parameters".
1.90 +<b>Therefore, by convention, <tt>.run()</tt> must be used
1.91 +explicitly to execute a function having named parameters
1.92 +everywhere in LEMON.</b>
1.93
1.94 +\section named-templ-func-param Named Function Template Parameters
1.95 +
1.96 +A named parameter can also be a template functions. The usage is
1.97 +exactly the same, but the implementation behind is a kind of black
1.98 +magic and they are the dirtiest part of the LEMON code.
1.99 +
1.100 +You will probably never need to know how it works, but if you really
1.101 +committed, have a look at \ref lemon/graph_to_eps.h for an example.
1.102
1.103  \section traits-classes Traits Classes
1.104
1.105 -The procedure above can also be applied when defining classes. In this
1.106 -case the type of the attributes can be changed.  Initially we have to
1.107 -define a class with the default attribute types. This is the so called
1.108 -Traits Class. Later on the types of these attributes can be changed,
1.109 -as described below. In our software \ref lemon::DijkstraDefaultTraits is an
1.110 -example of how a traits class looks like.
1.111 +A similar game can also be played when defining classes. In this case
1.112 +the type of the class attributes can be changed. Initially we have to
1.113 +define a special class called <em>Traits Class</em> defining the
1.114 +default type of the attributes. Then the types of these attributes can
1.115 +be changed in the same way as described in the next section.
1.116 +
1.117 +See \ref lemon::DijkstraDefaultTraits for an
1.118 +example how a traits class implementation looks like.
1.119
1.120  \section named-templ-param Named Class Template Parameters
1.121
1.122  If we would like to change the type of an attribute in a class that
1.123  was instantiated by using a traits class as a template parameter, and
1.124 -the class contains named parameters, we do not have to reinstantiate
1.125 -the class with new traits class. Instead of that, adaptor classes can
1.126 -be used like in the following cases.
1.127 +the class contains named parameters, we do not have to instantiate again
1.128 +the class with new traits class, but instead adaptor classes can
1.129 +be used as shown in the following example.
1.130
1.131  \code
1.132  Dijkstra<>::SetPredNodeMap<NullMap<Node,Node> >::Create
1.133 @@ -124,10 +116,4 @@
1.134  The result will be an instantiated Dijkstra class, in which the
1.135  DistMap and the PredMap is modified.
1.136
1.137 -\section named-templ-func-param Named Function Template Parameters
1.138 -
1.139 -If the class has so called wizard functions, the new class with the
1.140 -modified tpye of attributes can be returned by the appropriate wizard
1.141 -function. The usage of these wizard functions is the following:
1.142 -
1.143  */