alpar@267: /* -*- C++ -*- alpar@267: * alpar@267: * This file is a part of LEMON, a generic C++ optimization library alpar@267: * alpar@267: * Copyright (C) 2003-2008 alpar@267: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@267: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@267: * alpar@267: * Permission to use, modify and distribute this software is granted alpar@267: * provided that this copyright notice appears in all copies. For alpar@267: * precise terms see the accompanying LICENSE file. alpar@267: * alpar@267: * This software is provided "AS IS" with no warranty of any kind, alpar@267: * express or implied, and with no claim as to its suitability for any alpar@267: * purpose. alpar@267: * alpar@267: */ alpar@267: alpar@267: /*! alpar@267: alpar@267: \page named-param Named Parameters alpar@267: alpar@267: \section named-func-param Named Function Parameters alpar@267: alpar@268: Several modern languages provide a convenient way to refer the alpar@268: function parameters by name also when you call the function. It is alpar@268: especially comfortable in case of a function having tons of parameters alpar@268: with natural default values. Sadly, C++ lack this amenity. alpar@268: alpar@268: However, with a crafty trick and with some little alpar@268: inconvenience, it is possible to emulate is. alpar@268: The example below shows how to do it. alpar@267: alpar@267: \code alpar@267: class namedFn alpar@267: { alpar@267: int _id; alpar@267: double _val; alpar@267: int _dim; alpar@267: alpar@267: public: alpar@267: namedFn() : _id(0), _val(1), _dim(2) {} alpar@267: namedFn& id(int p) { _id = p ; return *this; } alpar@267: namedFn& val(double p) { _val = p ; return *this; } alpar@267: namedFn& dim(int p) { _dim = p ; return *this; } alpar@267: alpar@267: run() { alpar@268: std::cout << "Here comes the function itself\n" << alpar@268: << "With parameters " alpar@268: << _id << ", " << _val << ", " << _dim << std::endl; alpar@267: } alpar@267: }; alpar@267: \endcode alpar@267: alpar@268: Then you can use it like this. alpar@267: alpar@267: \code alpar@267: namedFn().id(3).val(2).run(); alpar@267: \endcode alpar@267: alpar@268: The trick is obvious, each "named parameter" changes one component of alpar@268: the underlying class, then gives back a reference to it. Finally, alpar@268: run() executes the algorithm itself. alpar@268: alpar@267: \note Although it is a class, namedFn is used pretty much like as it were alpar@268: a function. That it why we called it namedFn instead of \c NamedFn. alpar@267: alpar@268: \note In fact, the final .run() could be made unnecessary, alpar@268: because the algorithm could also be implemented in the destructor of alpar@268: \c namedFn instead. This however would make it impossible to implement alpar@268: functions with return values, and would also cause serious problems when alpar@268: implementing \ref named-templ-func-param "named template parameters". alpar@268: Therefore, by convention, .run() must be used alpar@268: explicitly to execute a function having named parameters alpar@268: everywhere in LEMON. alpar@267: alpar@268: \section named-templ-func-param Named Function Template Parameters alpar@268: alpar@268: A named parameter can also be a template functions. The usage is alpar@268: exactly the same, but the implementation behind is a kind of black alpar@268: magic and they are the dirtiest part of the LEMON code. alpar@268: alpar@268: You will probably never need to know how it works, but if you really alpar@268: committed, have a look at \ref lemon/graph_to_eps.h for an example. alpar@267: alpar@267: \section traits-classes Traits Classes alpar@267: alpar@268: A similar game can also be played when defining classes. In this case alpar@268: the type of the class attributes can be changed. Initially we have to alpar@268: define a special class called Traits Class defining the alpar@268: default type of the attributes. Then the types of these attributes can alpar@268: be changed in the same way as described in the next section. alpar@268: alpar@268: See \ref lemon::DijkstraDefaultTraits for an alpar@268: example how a traits class implementation looks like. alpar@267: alpar@267: \section named-templ-param Named Class Template Parameters alpar@267: alpar@267: If we would like to change the type of an attribute in a class that alpar@267: was instantiated by using a traits class as a template parameter, and alpar@268: the class contains named parameters, we do not have to instantiate again alpar@268: the class with new traits class, but instead adaptor classes can alpar@268: be used as shown in the following example. alpar@267: alpar@267: \code alpar@267: Dijkstra<>::SetPredNodeMap >::Create alpar@267: \endcode alpar@267: alpar@267: It can also be used in conjunction with other named template alpar@267: parameters in arbitrary order. alpar@267: alpar@267: \code alpar@267: Dijkstra<>::SetDistMap::SetPredMap >::Create alpar@267: \endcode alpar@267: alpar@267: The result will be an instantiated Dijkstra class, in which the alpar@267: DistMap and the PredMap is modified. alpar@267: alpar@267: */