]>
Commit | Line | Data |
---|---|---|
1 | <?xml version="1.0" encoding="utf-8" ?> | |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | |
3 | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |
4 | <head> | |
5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |
6 | <meta name="generator" content="Docutils 0.7: http://docutils.sourceforge.net/" /> | |
7 | <title>The Boost Parameter Library</title> | |
8 | <link rel="stylesheet" href="rst.css" type="text/css" /> | |
9 | </head> | |
10 | <body> | |
11 | <div class="document" id="the-boost-parameter-library"> | |
12 | <h1 class="title">The Boost Parameter Library</h1> | |
13 | ||
14 | <p><a class="reference external" href="../../../../index.htm"><img alt="Boost" src="../../../../boost.png" /></a></p> | |
15 | <hr class="docutils" /> | |
16 | <table class="docutils field-list" frame="void" rules="none"> | |
17 | <col class="field-name" /> | |
18 | <col class="field-body" /> | |
19 | <tbody valign="top"> | |
20 | <tr class="field"><th class="field-name">Abstract:</th><td class="field-body"><p class="first">Use this library to write functions and class templates | |
21 | that can accept arguments by name:</p> | |
22 | <pre class="literal-block"> | |
23 | new_window("alert", <strong>_width=10</strong>, <strong>_titlebar=false</strong>); | |
24 | ||
25 | smart_ptr< | |
26 | Foo | |
27 | , <strong>deleter<Deallocate<Foo> ></strong> | |
28 | , <strong>copy_policy<DeepCopy></strong> > p(new Foo); | |
29 | </pre> | |
30 | <p class="last">Since named arguments can be passed in any order, they are | |
31 | especially useful when a function or template has more than one | |
32 | parameter with a useful default value. The library also supports | |
33 | <em>deduced</em> parameters; that is to say, parameters whose identity | |
34 | can be deduced from their types.</p> | |
35 | </td> | |
36 | </tr> | |
37 | </tbody> | |
38 | </table> | |
39 | <!-- @jam_prefix.append(''' | |
40 | project test : requirements <include>. <implicit-dependency>/boost//headers ;''') --> | |
41 | <!-- @example.prepend(''' | |
42 | #include <boost/parameter.hpp> | |
43 | ||
44 | namespace test | |
45 | { | |
46 | BOOST_PARAMETER_NAME(title) | |
47 | BOOST_PARAMETER_NAME(width) | |
48 | BOOST_PARAMETER_NAME(titlebar) | |
49 | ||
50 | BOOST_PARAMETER_FUNCTION( | |
51 | (int), new_window, tag, (required (title,*)(width,*)(titlebar,*))) | |
52 | { | |
53 | return 0; | |
54 | } | |
55 | ||
56 | BOOST_PARAMETER_TEMPLATE_KEYWORD(deleter) | |
57 | BOOST_PARAMETER_TEMPLATE_KEYWORD(copy_policy) | |
58 | ||
59 | template <class T> struct Deallocate {}; | |
60 | struct DeepCopy {}; | |
61 | ||
62 | namespace parameter = boost::parameter; | |
63 | ||
64 | struct Foo {}; | |
65 | template <class T, class A0, class A1> | |
66 | struct smart_ptr | |
67 | { | |
68 | smart_ptr(Foo*); | |
69 | }; | |
70 | } | |
71 | using namespace test; | |
72 | int x = '''); --> | |
73 | <!-- @test('compile') --> | |
74 | <hr class="docutils" /> | |
75 | <table class="docutils field-list" frame="void" rules="none"> | |
76 | <col class="field-name" /> | |
77 | <col class="field-body" /> | |
78 | <tbody valign="top"> | |
79 | <tr class="field"><th class="field-name">Authors:</th><td class="field-body">David Abrahams, Daniel Wallin</td> | |
80 | </tr> | |
81 | <tr class="field"><th class="field-name">Contact:</th><td class="field-body"><a class="reference external" href="mailto:dave@boost-consulting.com">dave@boost-consulting.com</a>, <a class="reference external" href="mailto:daniel@boostpro.com">daniel@boostpro.com</a></td> | |
82 | </tr> | |
83 | <tr class="field"><th class="field-name">organization:</th><td class="field-body"><a class="reference external" href="http://www.boostpro.com">BoostPro Computing</a></td> | |
84 | </tr> | |
85 | <tr class="field"><th class="field-name">date:</th><td class="field-body">$Date: 2005/07/17 19:53:01 $</td> | |
86 | </tr> | |
87 | <tr class="field"><th class="field-name">copyright:</th><td class="field-body">Copyright David Abrahams, Daniel Wallin | |
88 | 2005-2009. Distributed under the Boost Software License, | |
89 | Version 1.0. (See accompanying file LICENSE_1_0.txt | |
90 | or copy at <a class="reference external" href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</td> | |
91 | </tr> | |
92 | </tbody> | |
93 | </table> | |
94 | <hr class="docutils" /> | |
95 | <p>[Note: this tutorial does not cover all details of the library. Please see also the <a class="reference external" href="reference.html">reference documentation</a>]</p> | |
96 | <div class="contents topic" id="table-of-contents"> | |
97 | <p class="topic-title first"><strong>Table of Contents</strong></p> | |
98 | <ul class="auto-toc simple"> | |
99 | <li><a class="reference internal" href="#motivation" id="id22">1 Motivation</a><ul class="auto-toc"> | |
100 | <li><a class="reference internal" href="#named-function-parameters" id="id23">1.1 Named Function Parameters</a></li> | |
101 | <li><a class="reference internal" href="#deduced-function-parameters" id="id24">1.2 Deduced Function Parameters</a></li> | |
102 | <li><a class="reference internal" href="#class-template-parameter-support" id="id25">1.3 Class Template Parameter Support</a></li> | |
103 | </ul> | |
104 | </li> | |
105 | <li><a class="reference internal" href="#tutorial" id="id26">2 Tutorial</a><ul class="auto-toc"> | |
106 | <li><a class="reference internal" href="#parameter-enabled-functions" id="id27">2.1 Parameter-Enabled Functions</a></li> | |
107 | <li><a class="reference internal" href="#parameter-enabled-member-functions" id="id28">2.2 Parameter-Enabled Member Functions</a></li> | |
108 | <li><a class="reference internal" href="#parameter-enabled-constructors" id="id29">2.3 Parameter-Enabled Constructors</a></li> | |
109 | <li><a class="reference internal" href="#parameter-enabled-class-templates" id="id30">2.4 Parameter-Enabled Class Templates</a></li> | |
110 | </ul> | |
111 | </li> | |
112 | <li><a class="reference internal" href="#advanced-topics" id="id31">3 Advanced Topics</a><ul class="auto-toc"> | |
113 | <li><a class="reference internal" href="#fine-grained-name-control" id="id32">3.1 Fine-Grained Name Control</a></li> | |
114 | <li><a class="reference internal" href="#more-argumentpacks" id="id33">3.2 More <span class="concept">ArgumentPack</span>s</a></li> | |
115 | </ul> | |
116 | </li> | |
117 | <li><a class="reference internal" href="#best-practices" id="id34">4 Best Practices</a><ul class="auto-toc"> | |
118 | <li><a class="reference internal" href="#keyword-naming" id="id35">4.1 Keyword Naming</a></li> | |
119 | <li><a class="reference internal" href="#namespaces" id="id36">4.2 Namespaces</a></li> | |
120 | <li><a class="reference internal" href="#documentation" id="id37">4.3 Documentation</a></li> | |
121 | </ul> | |
122 | </li> | |
123 | <li><a class="reference internal" href="#portability-considerations" id="id38">5 Portability Considerations</a><ul class="auto-toc"> | |
124 | <li><a class="reference internal" href="#no-sfinae-support" id="id39">5.1 No SFINAE Support</a></li> | |
125 | <li><a class="reference internal" href="#no-support-for-result-of" id="id40">5.2 No Support for <tt class="docutils literal">result_of</tt></a></li> | |
126 | <li><a class="reference internal" href="#compiler-can-t-see-references-in-unnamed-namespace" id="id41">5.3 Compiler Can't See References In Unnamed Namespace</a></li> | |
127 | </ul> | |
128 | </li> | |
129 | <li><a class="reference internal" href="#python-binding" id="id42">6 Python Binding</a></li> | |
130 | <li><a class="reference internal" href="#reference" id="id43">7 Reference</a></li> | |
131 | <li><a class="reference internal" href="#glossary" id="id44">8 Glossary</a></li> | |
132 | <li><a class="reference internal" href="#acknowledgements" id="id45">9 Acknowledgements</a></li> | |
133 | </ul> | |
134 | </div> | |
135 | <hr class="docutils" /> | |
136 | <div class="section" id="motivation"> | |
137 | <h1><a class="toc-backref" href="#id22">1 Motivation</a></h1> | |
138 | <p>In C++, <a class="reference internal" href="#arguments">arguments</a> are normally given meaning by their positions | |
139 | with respect to a <a class="reference internal" href="#parameter">parameter</a> list: the first argument passed maps | |
140 | onto the first parameter in a function's definition, and so on. | |
141 | That protocol is fine when there is at most one parameter with a | |
142 | default value, but when there are even a few useful defaults, the | |
143 | positional interface becomes burdensome:</p> | |
144 | <ul> | |
145 | <li><div class="first compound"> | |
146 | <p class="compound-first">Since an argument's meaning is given by its position, we have to | |
147 | choose an (often arbitrary) order for parameters with default | |
148 | values, making some combinations of defaults unusable:</p> | |
149 | <pre class="compound-middle literal-block"> | |
150 | window* new_window( | |
151 | char const* name, | |
152 | <strong>int border_width = default_border_width,</strong> | |
153 | bool movable = true, | |
154 | bool initially_visible = true | |
155 | ); | |
156 | ||
157 | const bool movability = false; | |
158 | window* w = new_window("alert box", movability); | |
159 | </pre> | |
160 | <p class="compound-middle">In the example above we wanted to make an unmoveable window | |
161 | with a default <tt class="docutils literal">border_width</tt>, but instead we got a moveable | |
162 | window with a <tt class="docutils literal">border_width</tt> of zero. To get the desired | |
163 | effect, we'd need to write:</p> | |
164 | <pre class="compound-last literal-block"> | |
165 | window* w = new_window( | |
166 | "alert box", <strong>default_border_width</strong>, movability); | |
167 | </pre> | |
168 | </div> | |
169 | </li> | |
170 | <li><div class="first compound"> | |
171 | <p class="compound-first">It can become difficult for readers to understand the meaning of | |
172 | arguments at the call site:</p> | |
173 | <pre class="compound-middle literal-block"> | |
174 | window* w = new_window("alert", 1, true, false); | |
175 | </pre> | |
176 | <p class="compound-last">Is this window moveable and initially invisible, or unmoveable | |
177 | and initially visible? The reader needs to remember the order | |
178 | of arguments to be sure.</p> | |
179 | </div> | |
180 | </li> | |
181 | <li><p class="first">The author of the call may not remember the order of the | |
182 | arguments either, leading to hard-to-find bugs.</p> | |
183 | </li> | |
184 | </ul> | |
185 | <!-- @ignore(3) --> | |
186 | <div class="section" id="named-function-parameters"> | |
187 | <h2><a class="toc-backref" href="#id23">1.1 Named Function Parameters</a></h2> | |
188 | <div class="compound"> | |
189 | <p class="compound-first">This library addresses the problems outlined above by associating | |
190 | each parameter name with a keyword object. Now users can identify | |
191 | arguments by name, rather than by position:</p> | |
192 | <pre class="compound-last literal-block"> | |
193 | window* w = new_window("alert box", <strong>movable_=</strong>false); // OK! | |
194 | </pre> | |
195 | </div> | |
196 | <!-- @ignore() --> | |
197 | </div> | |
198 | <div class="section" id="deduced-function-parameters"> | |
199 | <h2><a class="toc-backref" href="#id24">1.2 Deduced Function Parameters</a></h2> | |
200 | <div class="compound"> | |
201 | <p class="compound-first">A <strong>deduced parameter</strong> can be passed in any position <em>without</em> | |
202 | supplying an explicit parameter name. It's not uncommon for a | |
203 | function to have parameters that can be uniquely identified based | |
204 | on the types of arguments passed. The <tt class="docutils literal">name</tt> parameter to | |
205 | <tt class="docutils literal">new_window</tt> is one such example. None of the other arguments, | |
206 | if valid, can reasonably be converted to a <tt class="docutils literal">char const*</tt>. With | |
207 | a deduced parameter interface, we could pass the window name in | |
208 | <em>any</em> argument position without causing ambiguity:</p> | |
209 | <pre class="compound-middle literal-block"> | |
210 | window* w = new_window(movable_=false, <strong>"alert box"</strong>); // OK! | |
211 | window* w = new_window(<strong>"alert box"</strong>, movable_=false); // OK! | |
212 | </pre> | |
213 | <p class="compound-last">Appropriately used, a deduced parameter interface can free the | |
214 | user of the burden of even remembering the formal parameter | |
215 | names.</p> | |
216 | </div> | |
217 | <!-- @ignore() --> | |
218 | </div> | |
219 | <div class="section" id="class-template-parameter-support"> | |
220 | <h2><a class="toc-backref" href="#id25">1.3 Class Template Parameter Support</a></h2> | |
221 | <div class="compound"> | |
222 | <p class="compound-first">The reasoning we've given for named and deduced parameter | |
223 | interfaces applies equally well to class templates as it does to | |
224 | functions. Using the Parameter library, we can create interfaces | |
225 | that allow template arguments (in this case <tt class="docutils literal">shared</tt> and | |
226 | <tt class="docutils literal">Client</tt>) to be explicitly named, like this:</p> | |
227 | <pre class="compound-middle literal-block"> | |
228 | smart_ptr<<strong>ownership<shared></strong>, <strong>value_type<Client></strong> > p; | |
229 | </pre> | |
230 | <p class="compound-middle">The syntax for passing named template arguments is not quite as | |
231 | natural as it is for function arguments (ideally, we'd be able to | |
232 | write <tt class="docutils literal"><span class="pre">smart_ptr<ownership=shared,…></span></tt>). This small syntactic | |
233 | deficiency makes deduced parameters an especially big win when | |
234 | used with class templates:</p> | |
235 | <pre class="compound-last literal-block"> | |
236 | // <em>p and q could be equivalent, given a deduced</em> | |
237 | // <em>parameter interface.</em> | |
238 | smart_ptr<<strong>shared</strong>, <strong>Client</strong>> p; | |
239 | smart_ptr<<strong>Client</strong>, <strong>shared</strong>> q; | |
240 | </pre> | |
241 | </div> | |
242 | <!-- @ignore(2) --> | |
243 | </div> | |
244 | </div> | |
245 | <div class="section" id="tutorial"> | |
246 | <h1><a class="toc-backref" href="#id26">2 Tutorial</a></h1> | |
247 | <p>This tutorial shows all the basics—how to build both named- and deduced-parameter | |
248 | interfaces to function templates and class templates—and several | |
249 | more advanced idioms as well.</p> | |
250 | <div class="section" id="parameter-enabled-functions"> | |
251 | <h2><a class="toc-backref" href="#id27">2.1 Parameter-Enabled Functions</a></h2> | |
252 | <p>In this section we'll show how the Parameter library can be used to | |
253 | build an expressive interface to the <a class="reference external" href="../../../graph/index.html">Boost Graph library</a>'s | |
254 | <a class="reference external" href="../../../graph/doc/depth_first_search.html"><tt class="docutils literal">depth_first_search</tt></a> algorithm.<a class="footnote-reference" href="#old-interface" id="id3"><sup>1</sup></a></p> | |
255 | <!-- Revisit this | |
256 | ||
257 | After laying some groundwork | |
258 | and describing the algorithm's abstract interface, we'll show you | |
259 | how to build a basic implementation with keyword support. Then | |
260 | we'll add support for default arguments and we'll gradually refine the | |
261 | implementation with syntax improvements. Finally we'll show how to | |
262 | streamline the implementation of named parameter interfaces, | |
263 | improve their participation in overload resolution, and optimize | |
264 | their runtime efficiency. --> | |
265 | <div class="section" id="headers-and-namespaces"> | |
266 | <h3>2.1.1 Headers And Namespaces</h3> | |
267 | <p>Most components of the Parameter library are declared in a | |
268 | header named for the component. For example,</p> | |
269 | <pre class="literal-block"> | |
270 | #include <boost/parameter/keyword.hpp> | |
271 | </pre> | |
272 | <p>will ensure <tt class="docutils literal"><span class="pre">boost::parameter::keyword</span></tt> is known to the | |
273 | compiler. There is also a combined header, | |
274 | <tt class="docutils literal">boost/parameter.hpp</tt>, that includes most of the library's | |
275 | components. For the the rest of this tutorial, unless we say | |
276 | otherwise, you can use the rule above to figure out which header | |
277 | to <tt class="docutils literal">#include</tt> to access any given component of the library.</p> | |
278 | <!-- @example.append(''' | |
279 | using boost::parameter::keyword; | |
280 | ''') --> | |
281 | <!-- @test('compile') --> | |
282 | <p>Also, the examples below will also be written as if the | |
283 | namespace alias</p> | |
284 | <pre class="literal-block"> | |
285 | namespace parameter = boost::parameter; | |
286 | </pre> | |
287 | <!-- @ignore() --> | |
288 | <p>has been declared: we'll write <tt class="docutils literal"><span class="pre">parameter::xxx</span></tt> instead of | |
289 | <tt class="docutils literal"><span class="pre">boost::parameter::xxx</span></tt>.</p> | |
290 | </div> | |
291 | <div class="section" id="the-abstract-interface-to-dfs"> | |
292 | <h3>2.1.2 The Abstract Interface to <tt class="docutils literal">depth_first_search</tt></h3> | |
293 | <p>The Graph library's <tt class="docutils literal">depth_first_search</tt> algorithm is a generic function accepting | |
294 | from one to four arguments by reference. If all arguments were | |
295 | required, its signature might be as follows:</p> | |
296 | <pre class="literal-block"> | |
297 | template < | |
298 | class Graph, class DFSVisitor, class Index, class ColorMap | |
299 | > | |
300 | void depth_first_search( | |
301 | , Graph const& graph | |
302 | , DFSVisitor visitor | |
303 | , typename graph_traits<g>::vertex_descriptor root_vertex | |
304 | , IndexMap index_map | |
305 | , ColorMap& color); | |
306 | </pre> | |
307 | <!-- @ignore() --> | |
308 | <p>However, most of the parameters have a useful default value, as | |
309 | shown in the table below.</p> | |
310 | <table border="1" class="docutils" id="default-expressions"> | |
311 | <span id="parameter-table"></span><caption><tt class="docutils literal">depth_first_search</tt> Parameters</caption> | |
312 | <colgroup> | |
313 | <col width="17%" /> | |
314 | <col width="11%" /> | |
315 | <col width="35%" /> | |
316 | <col width="37%" /> | |
317 | </colgroup> | |
318 | <thead valign="bottom"> | |
319 | <tr><th class="head">Parameter Name</th> | |
320 | <th class="head">Dataflow</th> | |
321 | <th class="head">Type</th> | |
322 | <th class="head">Default Value (if any)</th> | |
323 | </tr> | |
324 | </thead> | |
325 | <tbody valign="top"> | |
326 | <tr><td><tt class="docutils literal">graph</tt></td> | |
327 | <td>in</td> | |
328 | <td>Model of <a class="reference external" href="../../../graph/doc/IncidenceGraph.html"><span class="concept">Incidence Graph</span></a> and | |
329 | <a class="reference external" href="../../../graph/doc/VertexListGraph.html"><span class="concept">Vertex List Graph</span></a></td> | |
330 | <td>none - this argument is required.</td> | |
331 | </tr> | |
332 | <tr><td><tt class="docutils literal">visitor</tt></td> | |
333 | <td>in</td> | |
334 | <td>Model of <a class="reference external" href="../../../graph/doc/DFSVisitor.html"><span class="concept">DFS Visitor</span></a></td> | |
335 | <td><tt class="docutils literal"><span class="pre">boost::dfs_visitor<>()</span></tt></td> | |
336 | </tr> | |
337 | <tr><td><tt class="docutils literal">root_vertex</tt></td> | |
338 | <td>in</td> | |
339 | <td><tt class="docutils literal">graph</tt>'s vertex descriptor | |
340 | type.</td> | |
341 | <td><tt class="docutils literal"><span class="pre">*vertices(graph).first</span></tt></td> | |
342 | </tr> | |
343 | <tr><td><tt class="docutils literal">index_map</tt></td> | |
344 | <td>in</td> | |
345 | <td>Model of <a class="reference external" href="../../../property_map/doc/ReadablePropertyMap.html"><span class="concept">Readable Property Map</span></a> | |
346 | with key type := <tt class="docutils literal">graph</tt>'s | |
347 | vertex descriptor and value type | |
348 | an integer type.</td> | |
349 | <td><tt class="docutils literal"><span class="pre">get(boost::vertex_index,graph)</span></tt></td> | |
350 | </tr> | |
351 | <tr><td><tt class="docutils literal">color_map</tt></td> | |
352 | <td>in/out</td> | |
353 | <td>Model of <a class="reference external" href="../../../property_map/doc/ReadWritePropertyMap.html"><span class="concept">Read/Write Property Map</span></a> | |
354 | with key type := <tt class="docutils literal">graph</tt>'s | |
355 | vertex descriptor type.</td> | |
356 | <td>an <tt class="docutils literal">iterator_property_map</tt> | |
357 | created from a <tt class="docutils literal"><span class="pre">std::vector</span></tt> of | |
358 | <tt class="docutils literal">default_color_type</tt> of size | |
359 | <tt class="docutils literal">num_vertices(graph)</tt> and using | |
360 | <tt class="docutils literal">index_map</tt> for the index map.</td> | |
361 | </tr> | |
362 | </tbody> | |
363 | </table> | |
364 | <p>Don't be intimidated by the information in the second and third | |
365 | columns above. For the purposes of this exercise, you don't need | |
366 | to understand them in detail.</p> | |
367 | </div> | |
368 | <div class="section" id="defining-the-keywords"> | |
369 | <h3>2.1.3 Defining the Keywords</h3> | |
370 | <p>The point of this exercise is to make it possible to call | |
371 | <tt class="docutils literal">depth_first_search</tt> with named arguments, leaving out any | |
372 | arguments for which the default is appropriate:</p> | |
373 | <pre class="literal-block"> | |
374 | graphs::depth_first_search(g, <strong>color_map_=my_color_map</strong>); | |
375 | </pre> | |
376 | <!-- @ignore() --> | |
377 | <p>To make that syntax legal, there needs to be an object called | |
378 | “<tt class="docutils literal">color_map_</tt>” whose assignment operator can accept a | |
379 | <tt class="docutils literal">my_color_map</tt> argument. In this step we'll create one such | |
380 | <strong>keyword object</strong> for each parameter. Each keyword object will be | |
381 | identified by a unique <strong>keyword tag type</strong>.</p> | |
382 | <!-- Revisit this | |
383 | ||
384 | We're going to define our interface in namespace ``graphs``. Since | |
385 | users need access to the keyword objects, but not the tag types, | |
386 | we'll define the keyword objects so they're accessible through | |
387 | ``graphs``, and we'll hide the tag types away in a nested | |
388 | namespace, ``graphs::tag``. The library provides a convenient | |
389 | macro for that purpose. --> | |
390 | <p>We're going to define our interface in namespace <tt class="docutils literal">graphs</tt>. The | |
391 | library provides a convenient macro for defining keyword objects:</p> | |
392 | <pre class="literal-block"> | |
393 | #include <boost/parameter/name.hpp> | |
394 | ||
395 | namespace graphs | |
396 | { | |
397 | BOOST_PARAMETER_NAME(graph) // Note: no semicolon | |
398 | BOOST_PARAMETER_NAME(visitor) | |
399 | BOOST_PARAMETER_NAME(root_vertex) | |
400 | BOOST_PARAMETER_NAME(index_map) | |
401 | BOOST_PARAMETER_NAME(color_map) | |
402 | } | |
403 | </pre> | |
404 | <!-- @test('compile') --> | |
405 | <p>The declaration of the <tt class="docutils literal">graph</tt> keyword you see here is | |
406 | equivalent to:</p> | |
407 | <pre class="literal-block"> | |
408 | namespace graphs | |
409 | { | |
410 | namespace tag { struct graph; } // keyword tag type | |
411 | ||
412 | namespace // unnamed | |
413 | { | |
414 | // A reference to the keyword object | |
415 | boost::parameter::keyword<tag::graph>& _graph | |
416 | = boost::parameter::keyword<tag::graph>::get(); | |
417 | } | |
418 | } | |
419 | </pre> | |
420 | <!-- @example.prepend('#include <boost/parameter/keyword.hpp>') --> | |
421 | <!-- @test('compile') --> | |
422 | <p>It defines a <em>keyword tag type</em> named <tt class="docutils literal"><span class="pre">tag::graph</span></tt> and a <em>keyword | |
423 | object</em> reference named <tt class="docutils literal">_graph</tt>.</p> | |
424 | <p>This “fancy dance” involving an unnamed namespace and references | |
425 | is all done to avoid violating the One Definition Rule (ODR)<a class="footnote-reference" href="#odr" id="id5"><sup>2</sup></a> when the named parameter interface is used by function | |
426 | templates that are instantiated in multiple translation | |
427 | units (MSVC6.x users see <a class="reference internal" href="#compiler-can-t-see-references-in-unnamed-namespace">this note</a>).</p> | |
428 | </div> | |
429 | <div class="section" id="writing-the-function"> | |
430 | <h3>2.1.4 Writing the Function</h3> | |
431 | <p>Now that we have our keywords defined, the function template | |
432 | definition follows a simple pattern using the | |
433 | <tt class="docutils literal">BOOST_PARAMETER_FUNCTION</tt> macro:</p> | |
434 | <pre class="literal-block"> | |
435 | #include <boost/parameter/preprocessor.hpp> | |
436 | ||
437 | namespace graphs | |
438 | { | |
439 | BOOST_PARAMETER_FUNCTION( | |
440 | (void), // 1. parenthesized return type | |
441 | depth_first_search, // 2. name of the function template | |
442 | ||
443 | tag, // 3. namespace of tag types | |
444 | ||
445 | (required (graph, *) ) // 4. one required parameter, and | |
446 | ||
447 | (optional // four optional parameters, with defaults | |
448 | (visitor, *, boost::dfs_visitor<>()) | |
449 | (root_vertex, *, *vertices(graph).first) | |
450 | (index_map, *, get(boost::vertex_index,graph)) | |
451 | (in_out(color_map), *, | |
452 | default_color_map(num_vertices(graph), index_map) ) | |
453 | ) | |
454 | ) | |
455 | { | |
456 | // ... body of function goes here... | |
457 | // use graph, visitor, index_map, and color_map | |
458 | } | |
459 | } | |
460 | </pre> | |
461 | <!-- @example.prepend(''' | |
462 | #include <boost/parameter/name.hpp> | |
463 | ||
464 | BOOST_PARAMETER_NAME(graph) | |
465 | BOOST_PARAMETER_NAME(visitor) | |
466 | BOOST_PARAMETER_NAME(root_vertex) | |
467 | BOOST_PARAMETER_NAME(index_map) | |
468 | BOOST_PARAMETER_NAME(color_map) | |
469 | ||
470 | namespace boost { | |
471 | ||
472 | template <class T = int> | |
473 | struct dfs_visitor | |
474 | {}; | |
475 | ||
476 | int vertex_index = 0; | |
477 | ||
478 | }''') --> | |
479 | <!-- @test('compile') --> | |
480 | <p>The arguments to <tt class="docutils literal">BOOST_PARAMETER_FUNCTION</tt> are:</p> | |
481 | <ol class="arabic simple"> | |
482 | <li>The return type of the resulting function template. Parentheses | |
483 | around the return type prevent any commas it might contain from | |
484 | confusing the preprocessor, and are always required.</li> | |
485 | <li>The name of the resulting function template.</li> | |
486 | <li>The name of a namespace where we can find tag types whose names | |
487 | match the function's parameter names.</li> | |
488 | <li>The function signature.</li> | |
489 | </ol> | |
490 | </div> | |
491 | <div class="section" id="function-signatures"> | |
492 | <h3>2.1.5 Function Signatures</h3> | |
493 | <p>Function signatures are described as one or two adjacent | |
494 | parenthesized terms (a <a class="reference external" href="../../../preprocessor/index.html">Boost.Preprocessor</a> <a class="reference external" href="http://boost-consulting.com/mplbook/preprocessor.html#sequences">sequence</a>) describing | |
495 | the function's parameters in the order in which they'd be expected | |
496 | if passed positionally. Any required parameters must come first, | |
497 | but the <tt class="docutils literal">(required … )</tt> clause can be omitted when all the | |
498 | parameters are optional.</p> | |
499 | <div class="section" id="required-parameters"> | |
500 | <h4>2.1.5.1 Required Parameters</h4> | |
501 | <div class="compound"> | |
502 | <p class="compound-first">Required parameters are given first—nested in a <tt class="docutils literal">(required … )</tt> | |
503 | clause—as a series of two-element tuples describing each parameter | |
504 | name and any requirements on the argument type. In this case there | |
505 | is only a single required parameter, so there's just a single | |
506 | tuple:</p> | |
507 | <pre class="compound-middle literal-block"> | |
508 | (required <strong>(graph, *)</strong> ) | |
509 | </pre> | |
510 | <p class="compound-last">Since <tt class="docutils literal">depth_first_search</tt> doesn't require any particular type | |
511 | for its <tt class="docutils literal">graph</tt> parameter, we use an asterix to indicate that | |
512 | any type is allowed. Required parameters must always precede any | |
513 | optional parameters in a signature, but if there are <em>no</em> | |
514 | required parameters, the <tt class="docutils literal">(required … )</tt> clause can be omitted | |
515 | entirely.</p> | |
516 | </div> | |
517 | <!-- @example.prepend(''' | |
518 | #include <boost/parameter.hpp> | |
519 | ||
520 | BOOST_PARAMETER_NAME(graph) | |
521 | ||
522 | BOOST_PARAMETER_FUNCTION((void), f, tag, | |
523 | ''') --> | |
524 | <!-- @example.append(') {}') --> | |
525 | <!-- @test('compile') --> | |
526 | </div> | |
527 | <div class="section" id="optional-parameters"> | |
528 | <h4>2.1.5.2 Optional Parameters</h4> | |
529 | <div class="compound"> | |
530 | <p class="compound-first">Optional parameters—nested in an <tt class="docutils literal">(optional … )</tt> clause—are given | |
531 | as a series of adjacent <em>three</em>-element tuples describing the | |
532 | parameter name, any requirements on the argument type, <em>and</em> and an | |
533 | expression representing the parameter's default value:</p> | |
534 | <pre class="compound-last literal-block"> | |
535 | (optional <strong> (visitor, *, boost::dfs_visitor<>()) | |
536 | (root_vertex, *, *vertices(graph).first) | |
537 | (index_map, *, get(boost::vertex_index,graph)) | |
538 | (in_out(color_map), *, | |
539 | default_color_map(num_vertices(graph), index_map) )</strong> | |
540 | ) | |
541 | </pre> | |
542 | </div> | |
543 | <!-- @example.prepend(''' | |
544 | #include <boost/parameter.hpp> | |
545 | ||
546 | namespace boost | |
547 | { | |
548 | int vertex_index = 0; | |
549 | ||
550 | template <class T = int> | |
551 | struct dfs_visitor | |
552 | {}; | |
553 | } | |
554 | ||
555 | BOOST_PARAMETER_NAME(graph) | |
556 | BOOST_PARAMETER_NAME(visitor) | |
557 | BOOST_PARAMETER_NAME(root_vertex) | |
558 | BOOST_PARAMETER_NAME(index_map) | |
559 | BOOST_PARAMETER_NAME(color_map) | |
560 | ||
561 | BOOST_PARAMETER_FUNCTION((void), f, tag, | |
562 | (required (graph, *)) | |
563 | ''') --> | |
564 | <!-- @example.append(') {}') --> | |
565 | <!-- @test('compile') --> | |
566 | </div> | |
567 | <div class="section" id="handling-out-parameters"> | |
568 | <h4>2.1.5.3 Handling “Out” Parameters</h4> | |
569 | <div class="compound"> | |
570 | <p class="compound-first">Within the function body, a parameter name such as <tt class="docutils literal">visitor</tt> is | |
571 | a <em>C++ reference</em>, bound either to an actual argument passed by | |
572 | the caller or to the result of evaluating a default expression. | |
573 | In most cases, parameter types are of the form <tt class="docutils literal">T const&</tt> for | |
574 | some <tt class="docutils literal">T</tt>. Parameters whose values are expected to be modified, | |
575 | however, must be passed by reference to <em>non</em>-<tt class="docutils literal">const</tt>. To | |
576 | indicate that <tt class="docutils literal">color_map</tt> is both read and written, we wrap | |
577 | its name in <tt class="docutils literal"><span class="pre">in_out(…)</span></tt>:</p> | |
578 | <pre class="compound-last literal-block"> | |
579 | (optional | |
580 | (visitor, *, boost::dfs_visitor<>()) | |
581 | (root_vertex, *, *vertices(graph).first) | |
582 | (index_map, *, get(boost::vertex_index,graph)) | |
583 | (<strong>in_out(color_map)</strong>, *, | |
584 | default_color_map(num_vertices(graph), index_map) ) | |
585 | ) | |
586 | </pre> | |
587 | </div> | |
588 | <!-- @example.prepend(''' | |
589 | #include <boost/parameter.hpp> | |
590 | ||
591 | namespace boost | |
592 | { | |
593 | int vertex_index = 0; | |
594 | ||
595 | template <class T = int> | |
596 | struct dfs_visitor | |
597 | {}; | |
598 | } | |
599 | ||
600 | BOOST_PARAMETER_NAME(graph) | |
601 | ||
602 | BOOST_PARAMETER_NAME(visitor) | |
603 | BOOST_PARAMETER_NAME(root_vertex) | |
604 | BOOST_PARAMETER_NAME(index_map) | |
605 | BOOST_PARAMETER_NAME(color_map) | |
606 | ||
607 | BOOST_PARAMETER_FUNCTION((void), f, tag, | |
608 | (required (graph, *)) | |
609 | ''') --> | |
610 | <!-- @example.append(') {}') --> | |
611 | <!-- @test('compile') --> | |
612 | <p>If <tt class="docutils literal">color_map</tt> were strictly going to be modified but not examined, | |
613 | we could have written <tt class="docutils literal">out(color_map)</tt>. There is no functional | |
614 | difference between <tt class="docutils literal">out</tt> and <tt class="docutils literal">in_out</tt>; the library provides | |
615 | both so you can make your interfaces more self-documenting.</p> | |
616 | </div> | |
617 | <div class="section" id="positional-arguments"> | |
618 | <h4>2.1.5.4 Positional Arguments</h4> | |
619 | <p>When arguments are passed positionally (without the use of | |
620 | keywords), they will be mapped onto parameters in the order the | |
621 | parameters are given in the signature, so for example in this | |
622 | call</p> | |
623 | <pre class="literal-block"> | |
624 | graphs::depth_first_search(x, y); | |
625 | </pre> | |
626 | <!-- @ignore() --> | |
627 | <p><tt class="docutils literal">x</tt> will always be interpreted as a graph and <tt class="docutils literal">y</tt> will always | |
628 | be interpreted as a visitor.</p> | |
629 | </div> | |
630 | <div class="section" id="default-expression-evaluation"> | |
631 | <h4>2.1.5.5 Default Expression Evaluation</h4> | |
632 | <div class="compound"> | |
633 | <p class="compound-first">Note that in our example, the value of the graph parameter is | |
634 | used in the default expressions for <tt class="docutils literal">root_vertex</tt>, | |
635 | <tt class="docutils literal">index_map</tt> and <tt class="docutils literal">color_map</tt>.</p> | |
636 | <pre class="compound-middle literal-block"> | |
637 | (required (<strong>graph</strong>, *) ) | |
638 | (optional | |
639 | (visitor, *, boost::dfs_visitor<>()) | |
640 | (root_vertex, *, *vertices(<strong>graph</strong>).first) | |
641 | (index_map, *, get(boost::vertex_index,<strong>graph</strong>)) | |
642 | (in_out(color_map), *, | |
643 | default_color_map(num_vertices(<strong>graph</strong>), index_map) ) | |
644 | ) | |
645 | </pre> | |
646 | <!-- @ignore() --> | |
647 | <p class="compound-last">A default expression is evaluated in the context of all preceding | |
648 | parameters, so you can use any of their values by name.</p> | |
649 | </div> | |
650 | <div class="compound"> | |
651 | <p class="compound-first">A default expression is never evaluated—or even instantiated—if | |
652 | an actual argument is passed for that parameter. We can actually | |
653 | demonstrate that with our code so far by replacing the body of | |
654 | <tt class="docutils literal">depth_first_search</tt> with something that prints the arguments:</p> | |
655 | <pre class="compound-middle literal-block"> | |
656 | #include <boost/graph/depth_first_search.hpp> // for dfs_visitor | |
657 | ||
658 | BOOST_PARAMETER_FUNCTION( | |
659 | (void), depth_first_search, tag | |
660 | <em>…signature goes here…</em> | |
661 | ) | |
662 | { | |
663 | std::cout << "graph=" << graph << std::endl; | |
664 | std::cout << "visitor=" << visitor << std::endl; | |
665 | std::cout << "root_vertex=" << root_vertex << std::endl; | |
666 | std::cout << "index_map=" << index_map << std::endl; | |
667 | std::cout << "color_map=" << color_map << std::endl; | |
668 | } | |
669 | ||
670 | int main() | |
671 | { | |
672 | depth_first_search(1, 2, 3, 4, 5); | |
673 | ||
674 | depth_first_search( | |
675 | "1", '2', _color_map = '5', | |
676 | _index_map = "4", _root_vertex = "3"); | |
677 | } | |
678 | </pre> | |
679 | <p class="compound-last">Despite the fact that default expressions such as | |
680 | <tt class="docutils literal"><span class="pre">vertices(graph).first</span></tt> are ill-formed for the given <tt class="docutils literal">graph</tt> | |
681 | arguments, both calls will compile, and each one will print | |
682 | exactly the same thing.</p> | |
683 | </div> | |
684 | <!-- @example.prepend(''' | |
685 | #include <boost/parameter.hpp> | |
686 | #include <iostream> | |
687 | ||
688 | BOOST_PARAMETER_NAME(graph) | |
689 | BOOST_PARAMETER_NAME(visitor) | |
690 | BOOST_PARAMETER_NAME(root_vertex) | |
691 | BOOST_PARAMETER_NAME(index_map) | |
692 | BOOST_PARAMETER_NAME(color_map)''') --> | |
693 | <!-- @example.replace_emphasis(''' | |
694 | , (required | |
695 | (graph, *) | |
696 | (visitor, *) | |
697 | (root_vertex, *) | |
698 | (index_map, *) | |
699 | (color_map, *) | |
700 | ) | |
701 | ''') --> | |
702 | <!-- @test('compile') --> | |
703 | </div> | |
704 | <div class="section" id="signature-matching-and-overloading"> | |
705 | <h4>2.1.5.6 Signature Matching and Overloading</h4> | |
706 | <p>In fact, the function signature is so general that any call to | |
707 | <tt class="docutils literal">depth_first_search</tt> with fewer than five arguments will match | |
708 | our function, provided we pass <em>something</em> for the required | |
709 | <tt class="docutils literal">graph</tt> parameter. That might not seem to be a problem at first; | |
710 | after all, if the arguments don't match the requirements imposed by | |
711 | the implementation of <tt class="docutils literal">depth_first_search</tt>, a compilation error | |
712 | will occur later, when its body is instantiated.</p> | |
713 | <p>There are at least three problems with very general function | |
714 | signatures.</p> | |
715 | <ol class="arabic simple"> | |
716 | <li>By the time our <tt class="docutils literal">depth_first_search</tt> is instantiated, it has | |
717 | been selected as the best matching overload. Some other | |
718 | <tt class="docutils literal">depth_first_search</tt> overload might've worked had it been | |
719 | chosen instead. By the time we see a compilation error, there's | |
720 | no chance to change that decision.</li> | |
721 | <li>Even if there are no overloads, error messages generated at | |
722 | instantiation time usually expose users to confusing | |
723 | implementation details. For example, users might see references | |
724 | to names generated by <tt class="docutils literal">BOOST_PARAMETER_FUNCTION</tt> such as | |
725 | <tt class="docutils literal"><span class="pre">graphs::detail::depth_first_search_with_named_params</span></tt> (or | |
726 | worse—think of the kinds of errors you get from your STL | |
727 | implementation when you make a mistake).<a class="footnote-reference" href="#conceptcpp" id="id7"><sup>4</sup></a></li> | |
728 | <li>The problems with exposing such permissive function template | |
729 | signatures have been the subject of much discussion, especially | |
730 | in the presence of <a class="reference external" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#225">unqualified calls</a>. If all we want is to | |
731 | avoid unintentional argument-dependent lookup (ADL), we can | |
732 | isolate <tt class="docutils literal">depth_first_search</tt> in a namespace containing no | |
733 | types<a class="footnote-reference" href="#using" id="id8"><sup>6</sup></a>, but suppose we <em>want</em> it to found via ADL?</li> | |
734 | </ol> | |
735 | <p>It's usually a good idea to prevent functions from being considered | |
736 | for overload resolution when the passed argument types aren't | |
737 | appropriate. The library already does this when the required | |
738 | <tt class="docutils literal">graph</tt> parameter is not supplied, but we're not likely to see a | |
739 | depth first search that doesn't take a graph to operate on. | |
740 | Suppose, instead, that we found a different depth first search | |
741 | algorithm that could work on graphs that don't model | |
742 | <a class="reference external" href="../../../graph/doc/IncidenceGraph.html"><span class="concept">Incidence Graph</span></a>? If we just added a simple overload, | |
743 | it would be ambiguous:</p> | |
744 | <pre class="literal-block"> | |
745 | // new overload | |
746 | BOOST_PARAMETER_FUNCTION( | |
747 | (void), depth_first_search, (tag), (required (graph,*))( … )) | |
748 | { | |
749 | // new algorithm implementation | |
750 | } | |
751 | ||
752 | … | |
753 | ||
754 | // ambiguous! | |
755 | depth_first_search(boost::adjacency_list<>(), 2, "hello"); | |
756 | </pre> | |
757 | <!-- @ignore() --> | |
758 | <div class="section" id="adding-type-requirements"> | |
759 | <h5>2.1.5.6.1 Adding Type Requirements</h5> | |
760 | <p>We really don't want the compiler to consider the original version | |
761 | of <tt class="docutils literal">depth_first_search</tt> because the <tt class="docutils literal">root_vertex</tt> argument, | |
762 | <tt class="docutils literal">"hello"</tt>, doesn't meet the <a class="reference internal" href="#parameter-table">requirement</a> that it match the | |
763 | <tt class="docutils literal">graph</tt> parameter's vertex descriptor type. Instead, this call | |
764 | should just invoke our new overload. To take the original | |
765 | <tt class="docutils literal">depth_first_search</tt> overload out of contention, we need to tell | |
766 | the library about this requirement by replacing the <tt class="docutils literal">*</tt> element | |
767 | of the signature with the required type, in parentheses:</p> | |
768 | <pre class="literal-block"> | |
769 | (root_vertex, | |
770 | <strong>(typename boost::graph_traits<graph_type>::vertex_descriptor)</strong>, | |
771 | *vertices(graph).first) | |
772 | </pre> | |
773 | <!-- @ignore() --> | |
774 | <p>Now the original <tt class="docutils literal">depth_first_search</tt> will only be called when | |
775 | the <tt class="docutils literal">root_vertex</tt> argument can be converted to the graph's vertex | |
776 | descriptor type, and our example that <em>was</em> ambiguous will smoothly | |
777 | call the new overload.</p> | |
778 | <div class="note"> | |
779 | <p class="first admonition-title">Note</p> | |
780 | <p class="last">The <em>type</em> of the <tt class="docutils literal">graph</tt> argument is available in the | |
781 | signature—and in the function body—as <tt class="docutils literal">graph_type</tt>. In | |
782 | general, to access the type of any parameter <em>foo</em>, write <em>foo</em><tt class="docutils literal">_type</tt>.</p> | |
783 | </div> | |
784 | </div> | |
785 | <div class="section" id="predicate-requirements"> | |
786 | <h5>2.1.5.6.2 Predicate Requirements</h5> | |
787 | <p>The requirements on other arguments are a bit more interesting than | |
788 | those on <tt class="docutils literal">root_vertex</tt>; they can't be described in terms of simple | |
789 | type matching. Instead, they must be described in terms of <a class="reference external" href="../../../mpl/doc/refmanual/metafunction.html">MPL | |
790 | Metafunctions</a>. There's no space to give a complete description | |
791 | of metafunctions or of graph library details here, but we'll show | |
792 | you the complete signature with maximal checking, just to give you | |
793 | a feel for how it's done. Each predicate metafunction is enclosed | |
794 | in parentheses <em>and preceded by an asterix</em>, as follows:</p> | |
795 | <pre class="literal-block"> | |
796 | // We first need to define a few metafunction that we use in the | |
797 | // predicates below. | |
798 | ||
799 | template <class G> | |
800 | struct traversal_category | |
801 | { | |
802 | typedef typename boost::graph_traits<G>::traversal_category type; | |
803 | }; | |
804 | ||
805 | template <class G> | |
806 | struct vertex_descriptor | |
807 | { | |
808 | typedef typename boost::graph_traits<G>::vertex_descriptor type; | |
809 | }; | |
810 | ||
811 | template <class G> | |
812 | struct value_type | |
813 | { | |
814 | typedef typename boost::property_traits<G>::value_type type; | |
815 | }; | |
816 | ||
817 | template <class G> | |
818 | struct key_type | |
819 | { | |
820 | typedef typename boost::property_traits<G>::key_type type; | |
821 | }; | |
822 | ||
823 | template<class Size, class IndexMap> | |
824 | boost::iterator_property_map< | |
825 | boost::default_color_type*, IndexMap | |
826 | , boost::default_color_type, boost::default_color_type& | |
827 | > | |
828 | default_color_map(Size num_vertices, IndexMap const& index_map) | |
829 | { | |
830 | std::vector<boost::default_color_type> colors(num_vertices); | |
831 | return &colors[0]; | |
832 | } | |
833 | ||
834 | BOOST_PARAMETER_FUNCTION( | |
835 | (void), depth_first_search, graphs | |
836 | ||
837 | , (required | |
838 | (graph | |
839 | , <strong>*(boost::mpl::and_< | |
840 | boost::is_convertible< | |
841 | traversal_category<_>, boost::incidence_graph_tag | |
842 | > | |
843 | , boost::is_convertible< | |
844 | traversal_category<_>, boost::vertex_list_graph_tag | |
845 | > | |
846 | >)</strong> )) | |
847 | ||
848 | (optional | |
849 | (visitor, *, boost::dfs_visitor<>()) // not checkable | |
850 | ||
851 | (root_vertex | |
852 | , (vertex_descriptor<graphs::graph::_>) | |
853 | , *vertices(graph).first) | |
854 | ||
855 | (index_map | |
856 | , <strong>*(boost::mpl::and_< | |
857 | boost::is_integral<value_type<_> > | |
858 | , boost::is_same< | |
859 | vertex_descriptor<graphs::graph::_>, key_type<_> | |
860 | > | |
861 | >)</strong> | |
862 | , get(boost::vertex_index,graph)) | |
863 | ||
864 | (in_out(color_map) | |
865 | , <strong>*(boost::is_same< | |
866 | vertex_descriptor<graphs::graph::_>, key_type<_> | |
867 | >)</strong> | |
868 | , default_color_map(num_vertices(graph), index_map) ) | |
869 | ) | |
870 | ) | |
871 | </pre> | |
872 | <!-- @example.prepend(''' | |
873 | #include <boost/parameter.hpp> | |
874 | #include <boost/graph/adjacency_list.hpp> | |
875 | #include <boost/graph/depth_first_search.hpp> | |
876 | ||
877 | BOOST_PARAMETER_NAME((_graph, graphs) graph) | |
878 | BOOST_PARAMETER_NAME((_visitor, graphs) visitor) | |
879 | BOOST_PARAMETER_NAME((_root_vertex, graphs) root_vertex) | |
880 | BOOST_PARAMETER_NAME((_index_map, graphs) index_map) | |
881 | BOOST_PARAMETER_NAME((_color_map, graphs) color_map) | |
882 | ||
883 | using boost::mpl::_; | |
884 | ''') --> | |
885 | <!-- @example.append(''' | |
886 | {} | |
887 | ||
888 | int main() | |
889 | { | |
890 | typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS> G; | |
891 | ||
892 | enum {u, v, w, x, y, z, N}; | |
893 | typedef std::pair<int, int> E; | |
894 | E edges[] = {E(u, v), E(u, x), E(x, v), E(y, x), E(v, y), E(w, y), | |
895 | E(w,z), E(z, z)}; | |
896 | G g(edges, edges + sizeof(edges) / sizeof(E), N); | |
897 | ||
898 | depth_first_search(g); | |
899 | depth_first_search(g, _root_vertex = (int)x); | |
900 | } | |
901 | ''') --> | |
902 | <!-- @test('compile') --> | |
903 | <p>Note the use of the nested <cite>tag::_</cite>. This is a shortcut for:</p> | |
904 | <pre class="literal-block"> | |
905 | value_type<boost::mpl::_2, tag> | |
906 | </pre> | |
907 | <!-- @ignore() --> | |
908 | <p>Intended to be used to access preceding arguments types in the | |
909 | predicates.</p> | |
910 | <p>We acknowledge that this signature is pretty hairy looking. | |
911 | Fortunately, it usually isn't necessary to so completely encode the | |
912 | type requirements on arguments to generic functions. However, it | |
913 | is usally worth the effort to do so: your code will be more | |
914 | self-documenting and will often provide a better user experience. | |
915 | You'll also have an easier transition to an upcoming C++ standard | |
916 | with <a class="reference external" href="http://www.generic-programming.org/software/ConceptGCC/">language support for concepts</a>.</p> | |
917 | </div> | |
918 | </div> | |
919 | <div class="section" id="deduced-parameters"> | |
920 | <h4>2.1.5.7 Deduced Parameters</h4> | |
921 | <p>To illustrate deduced parameter support we'll have to leave behind | |
922 | our example from the Graph library. Instead, consider the example | |
923 | of the <a class="reference external" href="../../../python/doc/v2/def.html"><tt class="docutils literal">def</tt></a> function from <a class="reference external" href="../../../python/doc/index.html">Boost.Python</a>. Its signature is | |
924 | roughly as follows:</p> | |
925 | <pre class="literal-block"> | |
926 | template < | |
927 | class Function, Class KeywordExpression, class CallPolicies | |
928 | > | |
929 | void def( | |
930 | // Required parameters | |
931 | char const* name, Function func | |
932 | ||
933 | // Optional, deduced parameters | |
934 | , char const* docstring = "" | |
935 | , KeywordExpression keywords = no_keywords() | |
936 | , CallPolicies policies = default_call_policies() | |
937 | ); | |
938 | </pre> | |
939 | <!-- @ignore() --> | |
940 | <p>Try not to be too distracted by the use of the term “keywords” in | |
941 | this example: although it means something analogous in Boost.Python | |
942 | to what it means in the Parameter library, for the purposes of this | |
943 | exercise you can think of it as being completely different.</p> | |
944 | <p>When calling <tt class="docutils literal">def</tt>, only two arguments are required. The | |
945 | association between any additional arguments and their parameters | |
946 | can be determined by the types of the arguments actually passed, so | |
947 | the caller is neither required to remember argument positions or | |
948 | explicitly specify parameter names for those arguments. To | |
949 | generate this interface using <tt class="docutils literal">BOOST_PARAMETER_FUNCTION</tt>, we need | |
950 | only enclose the deduced parameters in a <tt class="docutils literal">(deduced …)</tt> clause, as | |
951 | follows:</p> | |
952 | <pre class="literal-block"> | |
953 | namespace mpl = boost::mpl; | |
954 | ||
955 | BOOST_PARAMETER_FUNCTION( | |
956 | (void), def, tag, | |
957 | ||
958 | (required (name,(char const*)) (func,*) ) // nondeduced | |
959 | ||
960 | <strong>(deduced</strong> | |
961 | (optional | |
962 | (docstring, (char const*), "") | |
963 | ||
964 | (keywords | |
965 | , *(is_keyword_expression<mpl::_>) // see<a class="footnote-reference" href="#is-keyword-expression" id="id13"><sup>5</sup></a> | |
966 | , no_keywords()) | |
967 | ||
968 | (policies | |
969 | , *(mpl::not_< | |
970 | mpl::or_< | |
971 | boost::is_convertible<mpl::_, char const*> | |
972 | , is_keyword_expression<mpl::_> // see<a class="footnote-reference" href="#is-keyword-expression" id="id14"><sup>5</sup></a> | |
973 | > | |
974 | >) | |
975 | , default_call_policies() | |
976 | ) | |
977 | ) | |
978 | <strong>)</strong> | |
979 | ) | |
980 | { | |
981 | <em>…</em> | |
982 | } | |
983 | </pre> | |
984 | <!-- @example.replace_emphasis('') --> | |
985 | <!-- @example.prepend(''' | |
986 | #include <boost/parameter.hpp> | |
987 | ||
988 | BOOST_PARAMETER_NAME(name) | |
989 | BOOST_PARAMETER_NAME(func) | |
990 | BOOST_PARAMETER_NAME(docstring) | |
991 | BOOST_PARAMETER_NAME(keywords) | |
992 | BOOST_PARAMETER_NAME(policies) | |
993 | ||
994 | struct default_call_policies | |
995 | {}; | |
996 | ||
997 | struct no_keywords | |
998 | {}; | |
999 | ||
1000 | struct keywords | |
1001 | {}; | |
1002 | ||
1003 | template <class T> | |
1004 | struct is_keyword_expression | |
1005 | : boost::mpl::false_ | |
1006 | {}; | |
1007 | ||
1008 | template <> | |
1009 | struct is_keyword_expression<keywords> | |
1010 | : boost::mpl::true_ | |
1011 | {}; | |
1012 | ||
1013 | default_call_policies some_policies; | |
1014 | ||
1015 | void f() | |
1016 | {} | |
1017 | ||
1018 | ''') --> | |
1019 | <div class="admonition-syntax-note admonition"> | |
1020 | <p class="first admonition-title">Syntax Note</p> | |
1021 | <p class="last">A <tt class="docutils literal">(deduced …)</tt> clause always contains a <tt class="docutils literal">(required …)</tt> | |
1022 | and/or an <tt class="docutils literal">(optional …)</tt> subclause, and must follow any | |
1023 | <tt class="docutils literal">(required …)</tt> or <tt class="docutils literal">(optional …)</tt> clauses indicating | |
1024 | nondeduced parameters at the outer level.</p> | |
1025 | </div> | |
1026 | <p>With the declaration above, the following two calls are equivalent:</p> | |
1027 | <pre class="literal-block"> | |
1028 | def("f", &f, <strong>some_policies</strong>, <strong>"Documentation for f"</strong>); | |
1029 | def("f", &f, <strong>"Documentation for f"</strong>, <strong>some_policies</strong>); | |
1030 | </pre> | |
1031 | <!-- @example.prepend(''' | |
1032 | int main() | |
1033 | {''') --> | |
1034 | <p>If the user wants to pass a <tt class="docutils literal">policies</tt> argument that was also, | |
1035 | for some reason, convertible to <tt class="docutils literal">char const*</tt>, she can always | |
1036 | specify the parameter name explicitly, as follows:</p> | |
1037 | <pre class="literal-block"> | |
1038 | def( | |
1039 | "f", &f | |
1040 | , <strong>_policies = some_policies</strong>, "Documentation for f"); | |
1041 | </pre> | |
1042 | <!-- @example.append('}') --> | |
1043 | <!-- @test('compile', howmany='all') --> | |
1044 | </div> | |
1045 | </div> | |
1046 | </div> | |
1047 | <div class="section" id="parameter-enabled-member-functions"> | |
1048 | <h2><a class="toc-backref" href="#id28">2.2 Parameter-Enabled Member Functions</a></h2> | |
1049 | <p>The <tt class="docutils literal">BOOST_PARAMETER_MEMBER_FUNCTION</tt> and | |
1050 | <tt class="docutils literal">BOOST_PARAMETER_CONST_MEMBER_FUNCTION</tt> macros accept exactly the | |
1051 | same arguments as <tt class="docutils literal">BOOST_PARAMETER_FUNCTION</tt>, but are designed to | |
1052 | be used within the body of a class:</p> | |
1053 | <pre class="literal-block"> | |
1054 | BOOST_PARAMETER_NAME(arg1) | |
1055 | BOOST_PARAMETER_NAME(arg2) | |
1056 | ||
1057 | struct callable2 | |
1058 | { | |
1059 | BOOST_PARAMETER_CONST_MEMBER_FUNCTION( | |
1060 | (void), call, tag, (required (arg1,(int))(arg2,(int)))) | |
1061 | { | |
1062 | std::cout << arg1 << ", " << arg2 << std::endl; | |
1063 | } | |
1064 | }; | |
1065 | </pre> | |
1066 | <!-- @example.prepend(''' | |
1067 | #include <boost/parameter.hpp> | |
1068 | #include <iostream> | |
1069 | using namespace boost::parameter; | |
1070 | ''') --> | |
1071 | <!-- @test('compile') --> | |
1072 | <p>These macros don't directly allow a function's interface to be | |
1073 | separated from its implementation, but you can always forward | |
1074 | arguments on to a separate implementation function:</p> | |
1075 | <pre class="literal-block"> | |
1076 | struct callable2 | |
1077 | { | |
1078 | BOOST_PARAMETER_CONST_MEMBER_FUNCTION( | |
1079 | (void), call, tag, (required (arg1,(int))(arg2,(int)))) | |
1080 | { | |
1081 | call_impl(arg1,arg2); | |
1082 | } | |
1083 | private: | |
1084 | void call_impl(int, int); // implemented elsewhere. | |
1085 | }; | |
1086 | </pre> | |
1087 | <!-- @example.prepend(''' | |
1088 | #include <boost/parameter.hpp> | |
1089 | ||
1090 | BOOST_PARAMETER_NAME(arg1) | |
1091 | BOOST_PARAMETER_NAME(arg2) | |
1092 | using namespace boost::parameter; | |
1093 | ''') --> | |
1094 | <!-- @test('compile') --> | |
1095 | <div class="section" id="static-member-functions"> | |
1096 | <h3>2.2.1 Static Member Functions</h3> | |
1097 | <p>To expose a static member function, simply insert the keyword | |
1098 | “<tt class="docutils literal">static</tt>” before the function name:</p> | |
1099 | <pre class="literal-block"> | |
1100 | BOOST_PARAMETER_NAME(arg1) | |
1101 | ||
1102 | struct somebody | |
1103 | { | |
1104 | BOOST_PARAMETER_MEMBER_FUNCTION( | |
1105 | (void), <strong>static</strong> f, tag, (optional (arg1,(int),0))) | |
1106 | { | |
1107 | std::cout << arg1 << std::endl; | |
1108 | } | |
1109 | }; | |
1110 | </pre> | |
1111 | <!-- @example.prepend(''' | |
1112 | #include <boost/parameter.hpp> | |
1113 | #include <iostream> | |
1114 | using namespace boost::parameter; | |
1115 | ''') --> | |
1116 | <!-- @test('compile') --> | |
1117 | </div> | |
1118 | </div> | |
1119 | <div class="section" id="parameter-enabled-constructors"> | |
1120 | <h2><a class="toc-backref" href="#id29">2.3 Parameter-Enabled Constructors</a></h2> | |
1121 | <p>The lack of a “delegating constructor” | |
1122 | feature in C++ | |
1123 | (<a class="reference external" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf</a>) | |
1124 | limits somewhat the quality of interface this library can provide | |
1125 | for defining parameter-enabled constructors. The usual workaround | |
1126 | for a lack of constructor delegation applies: one must factor the | |
1127 | common logic into a base class.</p> | |
1128 | <p>Let's build a parameter-enabled constructor that simply prints its | |
1129 | arguments. The first step is to write a base class whose | |
1130 | constructor accepts a single argument known as an <a class="reference external" href="reference.html#argumentpack"><span class="concept">ArgumentPack</span></a>: | |
1131 | a bundle of references to the actual arguments, tagged with their | |
1132 | keywords. The values of the actual arguments are extracted from | |
1133 | the <span class="concept">ArgumentPack</span> by <em>indexing</em> it with keyword objects:</p> | |
1134 | <pre class="literal-block"> | |
1135 | BOOST_PARAMETER_NAME(name) | |
1136 | BOOST_PARAMETER_NAME(index) | |
1137 | ||
1138 | struct myclass_impl | |
1139 | { | |
1140 | template <class ArgumentPack> | |
1141 | myclass_impl(ArgumentPack const& args) | |
1142 | { | |
1143 | std::cout << "name = " << args[_name] | |
1144 | << "; index = " << args[_index | 42] | |
1145 | << std::endl; | |
1146 | } | |
1147 | }; | |
1148 | </pre> | |
1149 | <!-- @example.prepend(''' | |
1150 | #include <boost/parameter.hpp> | |
1151 | #include <iostream>''') --> | |
1152 | <p>Note that the bitwise or (“<tt class="docutils literal">|</tt>”) operator has a special | |
1153 | meaning when applied to keyword objects that are passed to an | |
1154 | <span class="concept">ArgumentPack</span>'s indexing operator: it is used to indicate a | |
1155 | default value. In this case if there is no <tt class="docutils literal">index</tt> parameter in | |
1156 | the <span class="concept">ArgumentPack</span>, <tt class="docutils literal">42</tt> will be used instead.</p> | |
1157 | <p>Now we are ready to write the parameter-enabled constructor | |
1158 | interface:</p> | |
1159 | <pre class="literal-block"> | |
1160 | struct myclass : myclass_impl | |
1161 | { | |
1162 | BOOST_PARAMETER_CONSTRUCTOR( | |
1163 | myclass, (myclass_impl), tag | |
1164 | , (required (name,*)) (optional (index,*))) // no semicolon | |
1165 | }; | |
1166 | </pre> | |
1167 | <p>Since we have supplied a default value for <tt class="docutils literal">index</tt> but not for | |
1168 | <tt class="docutils literal">name</tt>, only <tt class="docutils literal">name</tt> is required. We can exercise our new | |
1169 | interface as follows:</p> | |
1170 | <pre class="literal-block"> | |
1171 | myclass x("bob", 3); // positional | |
1172 | myclass y(_index = 12, _name = "sally"); // named | |
1173 | myclass z("june"); // positional/defaulted | |
1174 | </pre> | |
1175 | <!-- @example.wrap('int main() {', '}') --> | |
1176 | <!-- @test('run', howmany='all') --> | |
1177 | <p>For more on <span class="concept">ArgumentPack</span> manipulation, see the <a class="reference internal" href="#advanced-topics">Advanced Topics</a> | |
1178 | section.</p> | |
1179 | </div> | |
1180 | <div class="section" id="parameter-enabled-class-templates"> | |
1181 | <h2><a class="toc-backref" href="#id30">2.4 Parameter-Enabled Class Templates</a></h2> | |
1182 | <p>In this section we'll use Boost.Parameter to build <a class="reference external" href="../../../python/doc/index.html">Boost.Python</a>'s <a class="reference external" href="http://www.boost.org/libs/python/doc/v2/class.html#class_-spec">class_</a> template, whose “signature” is:</p> | |
1183 | <pre class="literal-block"> | |
1184 | template class< | |
1185 | ValueType, BaseList = bases<> | |
1186 | , HeldType = ValueType, Copyable = void | |
1187 | > | |
1188 | class class_; | |
1189 | </pre> | |
1190 | <!-- @ignore() --> | |
1191 | <p>Only the first argument, <tt class="docutils literal">ValueType</tt>, is required.</p> | |
1192 | <div class="section" id="named-template-parameters"> | |
1193 | <h3>2.4.1 Named Template Parameters</h3> | |
1194 | <p>First, we'll build an interface that allows users to pass arguments | |
1195 | positionally or by name:</p> | |
1196 | <pre class="literal-block"> | |
1197 | struct B { virtual ~B() = 0; }; | |
1198 | struct D : B { ~D(); }; | |
1199 | ||
1200 | class_< | |
1201 | <strong>class_type<B></strong>, <strong>copyable<boost::noncopyable></strong> | |
1202 | > …; | |
1203 | ||
1204 | class_< | |
1205 | <strong>D</strong>, <strong>held_type<std::auto_ptr<D> ></strong>, <strong>base_list<bases<B> ></strong> | |
1206 | > …; | |
1207 | </pre> | |
1208 | <!-- @ignore() --> | |
1209 | <div class="section" id="template-keywords"> | |
1210 | <h4>2.4.1.1 Template Keywords</h4> | |
1211 | <p>The first step is to define keywords for each template parameter:</p> | |
1212 | <pre class="literal-block"> | |
1213 | namespace boost { namespace python { | |
1214 | ||
1215 | BOOST_PARAMETER_TEMPLATE_KEYWORD(class_type) | |
1216 | BOOST_PARAMETER_TEMPLATE_KEYWORD(base_list) | |
1217 | BOOST_PARAMETER_TEMPLATE_KEYWORD(held_type) | |
1218 | BOOST_PARAMETER_TEMPLATE_KEYWORD(copyable) | |
1219 | ||
1220 | }} | |
1221 | </pre> | |
1222 | <!-- @example.prepend('#include <boost/parameter.hpp>') --> | |
1223 | <!-- @test('compile') --> | |
1224 | <p>The declaration of the <tt class="docutils literal">class_type</tt> keyword you see here is | |
1225 | equivalent to:</p> | |
1226 | <pre class="literal-block"> | |
1227 | namespace boost { namespace python { | |
1228 | ||
1229 | namespace tag { struct class_type; } // keyword tag type | |
1230 | template <class T> | |
1231 | struct class_type | |
1232 | : parameter::template_keyword<tag::class_type,T> | |
1233 | {}; | |
1234 | ||
1235 | }} | |
1236 | </pre> | |
1237 | <!-- @example.prepend('#include <boost/parameter.hpp>') --> | |
1238 | <!-- @test('compile') --> | |
1239 | <p>It defines a keyword tag type named <tt class="docutils literal"><span class="pre">tag::class_type</span></tt> and a | |
1240 | <em>parameter passing template</em> named <tt class="docutils literal">class_type</tt>.</p> | |
1241 | </div> | |
1242 | <div class="section" id="class-template-skeleton"> | |
1243 | <h4>2.4.1.2 Class Template Skeleton</h4> | |
1244 | <p>The next step is to define the skeleton of our class template, | |
1245 | which has three optional parameters. Because the user may pass | |
1246 | arguments in any order, we don't know the actual identities of | |
1247 | these parameters, so it would be premature to use descriptive names | |
1248 | or write out the actual default values for any of them. Instead, | |
1249 | we'll give them generic names and use the special type | |
1250 | <tt class="docutils literal"><span class="pre">boost::parameter::void_</span></tt> as a default:</p> | |
1251 | <pre class="literal-block"> | |
1252 | namespace boost { namespace python { | |
1253 | ||
1254 | template < | |
1255 | class A0 | |
1256 | , class A1 = parameter::void_ | |
1257 | , class A2 = parameter::void_ | |
1258 | , class A3 = parameter::void_ | |
1259 | > | |
1260 | struct class_ | |
1261 | { | |
1262 | <em>…</em> | |
1263 | }; | |
1264 | ||
1265 | }} | |
1266 | </pre> | |
1267 | <!-- @example.prepend('#include <boost/parameter.hpp>') --> | |
1268 | <!-- @example.replace_emphasis('') --> | |
1269 | <!-- @test('compile') --> | |
1270 | </div> | |
1271 | <div class="section" id="class-template-signatures"> | |
1272 | <h4>2.4.1.3 Class Template Signatures</h4> | |
1273 | <p>Next, we need to build a type, known as a <a class="reference external" href="reference.html#parameterspec"><span class="concept">ParameterSpec</span></a>, | |
1274 | describing the “signature” of <tt class="docutils literal"><span class="pre">boost::python::class_</span></tt>. A | |
1275 | <a class="reference external" href="reference.html#parameterspec"><span class="concept">ParameterSpec</span></a> enumerates the required and optional parameters in | |
1276 | their positional order, along with any type requirements (note that | |
1277 | it does <em>not</em> specify defaults -- those will be dealt with | |
1278 | separately):</p> | |
1279 | <pre class="literal-block"> | |
1280 | namespace boost { namespace python { | |
1281 | ||
1282 | using boost::mpl::_; | |
1283 | ||
1284 | typedef parameter::parameters< | |
1285 | required<tag::class_type, boost::is_class<_> > | |
1286 | , parameter::optional<tag::base_list, mpl::is_sequence<_> > | |
1287 | , parameter::optional<tag::held_type> | |
1288 | , parameter::optional<tag::copyable> | |
1289 | > class_signature; | |
1290 | ||
1291 | }} | |
1292 | </pre> | |
1293 | <!-- @example.prepend(''' | |
1294 | #include <boost/parameter.hpp> | |
1295 | #include <boost/mpl/is_sequence.hpp> | |
1296 | #include <boost/noncopyable.hpp> | |
1297 | #include <boost/type_traits/is_class.hpp> | |
1298 | #include <memory> | |
1299 | ||
1300 | using namespace boost::parameter; | |
1301 | ||
1302 | namespace boost { namespace python { | |
1303 | ||
1304 | BOOST_PARAMETER_TEMPLATE_KEYWORD(class_type) | |
1305 | BOOST_PARAMETER_TEMPLATE_KEYWORD(base_list) | |
1306 | BOOST_PARAMETER_TEMPLATE_KEYWORD(held_type) | |
1307 | BOOST_PARAMETER_TEMPLATE_KEYWORD(copyable) | |
1308 | ||
1309 | template <class B = int> | |
1310 | struct bases | |
1311 | {}; | |
1312 | ||
1313 | }}''') --> | |
1314 | </div> | |
1315 | <div class="section" id="argument-packs-and-parameter-extraction"> | |
1316 | <span id="binding-intro"></span><h4>2.4.1.4 Argument Packs and Parameter Extraction</h4> | |
1317 | <p>Next, within the body of <tt class="docutils literal">class_</tt> , we use the <span class="concept">ParameterSpec</span>'s | |
1318 | nested <tt class="docutils literal">::bind< … ></tt> template to bundle the actual arguments into an | |
1319 | <a class="reference external" href="reference.html#argumentpack"><span class="concept">ArgumentPack</span></a> type, and then use the library's <tt class="docutils literal">value_type< … ></tt> | |
1320 | metafunction to extract “logical parameters”. <tt class="docutils literal">value_type< … ></tt> is | |
1321 | a lot like <tt class="docutils literal">binding< … ></tt>, but no reference is added to the actual | |
1322 | argument type. Note that defaults are specified by passing it an | |
1323 | optional third argument:</p> | |
1324 | <pre class="literal-block"> | |
1325 | namespace boost { namespace python { | |
1326 | ||
1327 | template < | |
1328 | class A0 | |
1329 | , class A1 = parameter::void_ | |
1330 | , class A2 = parameter::void_ | |
1331 | , class A3 = parameter::void_ | |
1332 | > | |
1333 | struct class_ | |
1334 | { | |
1335 | // Create ArgumentPack | |
1336 | typedef typename | |
1337 | class_signature::bind<A0,A1,A2,A3>::type | |
1338 | args; | |
1339 | ||
1340 | // Extract first logical parameter. | |
1341 | typedef typename parameter::value_type< | |
1342 | args, tag::class_type>::type class_type; | |
1343 | ||
1344 | typedef typename parameter::value_type< | |
1345 | args, tag::base_list, bases<> >::type base_list; | |
1346 | ||
1347 | typedef typename parameter::value_type< | |
1348 | args, tag::held_type, class_type>::type held_type; | |
1349 | ||
1350 | typedef typename parameter::value_type< | |
1351 | args, tag::copyable, void>::type copyable; | |
1352 | }; | |
1353 | ||
1354 | }} | |
1355 | </pre> | |
1356 | </div> | |
1357 | </div> | |
1358 | <div class="section" id="exercising-the-code-so-far"> | |
1359 | <h3>2.4.2 Exercising the Code So Far</h3> | |
1360 | <div class="compound"> | |
1361 | <p class="compound-first">Revisiting our original examples,</p> | |
1362 | <pre class="compound-middle literal-block"> | |
1363 | typedef boost::python::class_< | |
1364 | class_type<B>, copyable<boost::noncopyable> | |
1365 | > c1; | |
1366 | ||
1367 | typedef boost::python::class_< | |
1368 | D, held_type<std::auto_ptr<D> >, base_list<bases<B> > | |
1369 | > c2; | |
1370 | </pre> | |
1371 | <!-- @example.prepend(''' | |
1372 | using boost::python::class_type; | |
1373 | using boost::python::copyable; | |
1374 | using boost::python::held_type; | |
1375 | using boost::python::base_list; | |
1376 | using boost::python::bases; | |
1377 | ||
1378 | struct B {}; | |
1379 | struct D {};''') --> | |
1380 | <p class="compound-middle">we can now examine the intended parameters:</p> | |
1381 | <pre class="compound-last literal-block"> | |
1382 | BOOST_MPL_ASSERT((boost::is_same<c1::class_type, B>)); | |
1383 | BOOST_MPL_ASSERT((boost::is_same<c1::base_list, bases<> >)); | |
1384 | BOOST_MPL_ASSERT((boost::is_same<c1::held_type, B>)); | |
1385 | BOOST_MPL_ASSERT(( | |
1386 | boost::is_same<c1::copyable, boost::noncopyable> | |
1387 | )); | |
1388 | ||
1389 | BOOST_MPL_ASSERT((boost::is_same<c2::class_type, D>)); | |
1390 | BOOST_MPL_ASSERT((boost::is_same<c2::base_list, bases<B> >)); | |
1391 | BOOST_MPL_ASSERT(( | |
1392 | boost::is_same<c2::held_type, std::auto_ptr<D> > | |
1393 | )); | |
1394 | BOOST_MPL_ASSERT((boost::is_same<c2::copyable, void>)); | |
1395 | </pre> | |
1396 | </div> | |
1397 | <!-- @test('compile', howmany='all') --> | |
1398 | </div> | |
1399 | <div class="section" id="deduced-template-parameters"> | |
1400 | <h3>2.4.3 Deduced Template Parameters</h3> | |
1401 | <p>To apply a deduced parameter interface here, we need only make the | |
1402 | type requirements a bit tighter so the <tt class="docutils literal">held_type</tt> and | |
1403 | <tt class="docutils literal">copyable</tt> parameters can be crisply distinguished from the | |
1404 | others. <a class="reference external" href="../../../python/doc/index.html">Boost.Python</a> does this by requiring that <tt class="docutils literal">base_list</tt> be | |
1405 | a specialization of its <tt class="docutils literal">bases< … ></tt> template (as opposed to | |
1406 | being any old MPL sequence) and by requiring that <tt class="docutils literal">copyable</tt>, if | |
1407 | explicitly supplied, be <tt class="docutils literal"><span class="pre">boost::noncopyable</span></tt>. One easy way of | |
1408 | identifying specializations of <tt class="docutils literal">bases< … ></tt> is to derive them all | |
1409 | from the same class, as an implementation detail:</p> | |
1410 | <pre class="literal-block"> | |
1411 | namespace boost { namespace python { | |
1412 | ||
1413 | namespace detail { struct bases_base {}; } | |
1414 | ||
1415 | template <class A0 = void, class A1 = void, class A2 = void <em>…</em> > | |
1416 | struct bases <strong>: detail::bases_base</strong> | |
1417 | {}; | |
1418 | ||
1419 | }} | |
1420 | </pre> | |
1421 | <!-- @example.replace_emphasis('') --> | |
1422 | <!-- @example.prepend(''' | |
1423 | #include <boost/parameter.hpp> | |
1424 | #include <boost/mpl/is_sequence.hpp> | |
1425 | #include <boost/noncopyable.hpp> | |
1426 | #include <memory> | |
1427 | ||
1428 | using namespace boost::parameter; | |
1429 | using boost::mpl::_; | |
1430 | ||
1431 | namespace boost { namespace python { | |
1432 | ||
1433 | BOOST_PARAMETER_TEMPLATE_KEYWORD(class_type) | |
1434 | BOOST_PARAMETER_TEMPLATE_KEYWORD(base_list) | |
1435 | BOOST_PARAMETER_TEMPLATE_KEYWORD(held_type) | |
1436 | BOOST_PARAMETER_TEMPLATE_KEYWORD(copyable) | |
1437 | ||
1438 | }}''') --> | |
1439 | <p>Now we can rewrite our signature to make all three optional | |
1440 | parameters deducible:</p> | |
1441 | <pre class="literal-block"> | |
1442 | typedef parameter::parameters< | |
1443 | required<tag::class_type, is_class<_> > | |
1444 | ||
1445 | , parameter::optional< | |
1446 | deduced<tag::base_list> | |
1447 | , is_base_and_derived<detail::bases_base,_> | |
1448 | > | |
1449 | ||
1450 | , parameter::optional< | |
1451 | deduced<tag::held_type> | |
1452 | , mpl::not_< | |
1453 | mpl::or_< | |
1454 | is_base_and_derived<detail::bases_base,_> | |
1455 | , is_same<noncopyable,_> | |
1456 | > | |
1457 | > | |
1458 | > | |
1459 | ||
1460 | , parameter::optional<deduced<tag::copyable>, is_same<noncopyable,_> > | |
1461 | ||
1462 | > class_signature; | |
1463 | </pre> | |
1464 | <!-- @example.prepend(''' | |
1465 | #include <boost/type_traits/is_class.hpp> | |
1466 | namespace boost { namespace python {''') --> | |
1467 | <!-- @example.append(''' | |
1468 | template < | |
1469 | class A0 | |
1470 | , class A1 = parameter::void_ | |
1471 | , class A2 = parameter::void_ | |
1472 | , class A3 = parameter::void_ | |
1473 | > | |
1474 | struct class_ | |
1475 | { | |
1476 | // Create ArgumentPack | |
1477 | typedef typename | |
1478 | class_signature::bind<A0,A1,A2,A3>::type | |
1479 | args; | |
1480 | ||
1481 | // Extract first logical parameter. | |
1482 | typedef typename parameter::value_type< | |
1483 | args, tag::class_type>::type class_type; | |
1484 | ||
1485 | typedef typename parameter::value_type< | |
1486 | args, tag::base_list, bases<> >::type base_list; | |
1487 | ||
1488 | typedef typename parameter::value_type< | |
1489 | args, tag::held_type, class_type>::type held_type; | |
1490 | ||
1491 | typedef typename parameter::value_type< | |
1492 | args, tag::copyable, void>::type copyable; | |
1493 | }; | |
1494 | ||
1495 | }}''') --> | |
1496 | <p>It may seem like we've added a great deal of complexity, but the | |
1497 | benefits to our users are greater. Our original examples can now | |
1498 | be written without explicit parameter names:</p> | |
1499 | <pre class="literal-block"> | |
1500 | typedef boost::python::class_<<strong>B</strong>, <strong>boost::noncopyable</strong>> c1; | |
1501 | ||
1502 | typedef boost::python::class_<<strong>D</strong>, <strong>std::auto_ptr<D></strong>, <strong>bases<B></strong> > c2; | |
1503 | </pre> | |
1504 | <!-- @example.prepend(''' | |
1505 | struct B {}; | |
1506 | struct D {}; | |
1507 | ||
1508 | using boost::python::bases;''') --> | |
1509 | <!-- @example.append(''' | |
1510 | BOOST_MPL_ASSERT((boost::is_same<c1::class_type, B>)); | |
1511 | BOOST_MPL_ASSERT((boost::is_same<c1::base_list, bases<> >)); | |
1512 | BOOST_MPL_ASSERT((boost::is_same<c1::held_type, B>)); | |
1513 | BOOST_MPL_ASSERT(( | |
1514 | boost::is_same<c1::copyable, boost::noncopyable> | |
1515 | )); | |
1516 | ||
1517 | BOOST_MPL_ASSERT((boost::is_same<c2::class_type, D>)); | |
1518 | BOOST_MPL_ASSERT((boost::is_same<c2::base_list, bases<B> >)); | |
1519 | BOOST_MPL_ASSERT(( | |
1520 | boost::is_same<c2::held_type, std::auto_ptr<D> > | |
1521 | )); | |
1522 | BOOST_MPL_ASSERT((boost::is_same<c2::copyable, void>));''') --> | |
1523 | <!-- @test('compile', howmany='all') --> | |
1524 | </div> | |
1525 | </div> | |
1526 | </div> | |
1527 | <div class="section" id="advanced-topics"> | |
1528 | <h1><a class="toc-backref" href="#id31">3 Advanced Topics</a></h1> | |
1529 | <p>At this point, you should have a good grasp of the basics. In this | |
1530 | section we'll cover some more esoteric uses of the library.</p> | |
1531 | <div class="section" id="fine-grained-name-control"> | |
1532 | <h2><a class="toc-backref" href="#id32">3.1 Fine-Grained Name Control</a></h2> | |
1533 | <p>If you don't like the leading-underscore naming convention used | |
1534 | to refer to keyword objects, or you need the name <tt class="docutils literal">tag</tt> for | |
1535 | something other than the keyword type namespace, there's another | |
1536 | way to use <tt class="docutils literal">BOOST_PARAMETER_NAME</tt>:</p> | |
1537 | <pre class="literal-block"> | |
1538 | BOOST_PARAMETER_NAME(<strong>(</strong><em>object-name</em><strong>,</strong> <em>tag-namespace</em><strong>)</strong> <em>parameter-name</em>) | |
1539 | </pre> | |
1540 | <!-- @ignore() --> | |
1541 | <p>Here is a usage example:</p> | |
1542 | <pre class="literal-block"> | |
1543 | BOOST_PARAMETER_NAME((<strong>pass_foo</strong>, <strong>keywords</strong>) <strong>foo</strong>) | |
1544 | ||
1545 | BOOST_PARAMETER_FUNCTION( | |
1546 | (int), f, | |
1547 | <strong>keywords</strong>, (required (<strong>foo</strong>, *))) | |
1548 | { | |
1549 | return <strong>foo</strong> + 1; | |
1550 | } | |
1551 | ||
1552 | int x = f(<strong>pass_foo</strong> = 41); | |
1553 | </pre> | |
1554 | <!-- @example.prepend('#include <boost/parameter.hpp>') --> | |
1555 | <!-- @example.append(''' | |
1556 | int main() | |
1557 | {}''') --> | |
1558 | <!-- @test('run') --> | |
1559 | <p>Before you use this more verbose form, however, please read the | |
1560 | section on <a class="reference internal" href="#keyword-naming">best practices for keyword object naming</a>.</p> | |
1561 | </div> | |
1562 | <div class="section" id="more-argumentpacks"> | |
1563 | <h2><a class="toc-backref" href="#id33">3.2 More <span class="concept">ArgumentPack</span>s</a></h2> | |
1564 | <p>We've already seen <span class="concept">ArgumentPack</span>s when we looked at | |
1565 | <a class="reference internal" href="#parameter-enabled-constructors">parameter-enabled constructors</a> and <a class="reference internal" href="#binding-intro">class templates</a>. As you | |
1566 | might have guessed, <span class="concept">ArgumentPack</span>s actually lie at the heart of | |
1567 | everything this library does; in this section we'll examine ways to | |
1568 | build and manipulate them more effectively.</p> | |
1569 | <div class="section" id="building-argumentpacks"> | |
1570 | <h3>3.2.1 Building <span class="concept">ArgumentPack</span>s</h3> | |
1571 | <p>The simplest <span class="concept">ArgumentPack</span> is the result of assigning into a | |
1572 | keyword object:</p> | |
1573 | <pre class="literal-block"> | |
1574 | BOOST_PARAMETER_NAME(index) | |
1575 | ||
1576 | template <class ArgumentPack> | |
1577 | int print_index(ArgumentPack const& args) | |
1578 | { | |
1579 | std::cout << "index = " << args[_index] << std::endl; | |
1580 | return 0; | |
1581 | } | |
1582 | ||
1583 | int x = print_index(_index = 3); // prints "index = 3" | |
1584 | </pre> | |
1585 | <!-- @example.prepend(''' | |
1586 | #include <boost/parameter.hpp> | |
1587 | #include <iostream>''') --> | |
1588 | <p>Also, <span class="concept">ArgumentPack</span>s can be composed using the comma operator. | |
1589 | The extra parentheses below are used to prevent the compiler from | |
1590 | seeing two separate arguments to <tt class="docutils literal">print_name_and_index</tt>:</p> | |
1591 | <pre class="literal-block"> | |
1592 | BOOST_PARAMETER_NAME(name) | |
1593 | ||
1594 | template <class ArgumentPack> | |
1595 | int print_name_and_index(ArgumentPack const& args) | |
1596 | { | |
1597 | std::cout << "name = " << args[_name] << "; "; | |
1598 | return print_index(args); | |
1599 | } | |
1600 | ||
1601 | int y = print_name_and_index((_index = 3, _name = "jones")); | |
1602 | </pre> | |
1603 | <p>To build an <span class="concept">ArgumentPack</span> with positional arguments, we can use a | |
1604 | <a class="reference external" href="reference.html#parameterspec"><span class="concept">ParameterSpec</span></a>. As introduced described in the section on <a class="reference internal" href="#class-template-signatures">Class | |
1605 | Template Signatures</a>, a <span class="concept">ParameterSpec</span> describes the positional | |
1606 | order of parameters and any associated type requirements. Just as | |
1607 | we can build an <span class="concept">ArgumentPack</span> <em>type</em> with its nested <tt class="docutils literal">::bind< … | |
1608 | ></tt> template, we can build an <span class="concept">ArgumentPack</span> <em>object</em> by invoking | |
1609 | its function call operator:</p> | |
1610 | <pre class="literal-block"> | |
1611 | parameter::parameters< | |
1612 | required<tag::name, is_convertible<_,char const*> > | |
1613 | , optional<tag::index, is_convertible<_,int> > | |
1614 | > spec; | |
1615 | ||
1616 | char const sam[] = "sam"; | |
1617 | int twelve = 12; | |
1618 | ||
1619 | int z0 = print_name_and_index( <strong>spec(</strong>sam, twelve<strong>)</strong> ); | |
1620 | ||
1621 | int z1 = print_name_and_index( | |
1622 | <strong>spec(</strong>_index=12, _name="sam"<strong>)</strong> | |
1623 | ); | |
1624 | </pre> | |
1625 | <!-- @example.prepend(''' | |
1626 | namespace parameter = boost::parameter; | |
1627 | using parameter::required; | |
1628 | using parameter::optional; | |
1629 | using boost::is_convertible; | |
1630 | using boost::mpl::_;''') --> | |
1631 | <!-- @example.append(''' | |
1632 | int main() | |
1633 | {}''') --> | |
1634 | <!-- @test('run', howmany='all') --> | |
1635 | <p>Note that because of the <a class="reference external" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm">forwarding problem</a>, <tt class="docutils literal"><span class="pre">parameter::parameters::operator()</span></tt> | |
1636 | can't accept non-const rvalues.</p> | |
1637 | </div> | |
1638 | <div class="section" id="extracting-parameter-types"> | |
1639 | <h3>3.2.2 Extracting Parameter Types</h3> | |
1640 | <p>If we want to know the types of the arguments passed to | |
1641 | <tt class="docutils literal">print_name_and_index</tt>, we have a couple of options. The | |
1642 | simplest and least error-prone approach is to forward them to a | |
1643 | function template and allow <em>it</em> to do type deduction:</p> | |
1644 | <pre class="literal-block"> | |
1645 | BOOST_PARAMETER_NAME(name) | |
1646 | BOOST_PARAMETER_NAME(index) | |
1647 | ||
1648 | template <class Name, class Index> | |
1649 | int deduce_arg_types_impl(Name& name, Index& index) | |
1650 | { | |
1651 | Name& n2 = name; // we know the types | |
1652 | Index& i2 = index; | |
1653 | return index; | |
1654 | } | |
1655 | ||
1656 | template <class ArgumentPack> | |
1657 | int deduce_arg_types(ArgumentPack const& args) | |
1658 | { | |
1659 | return deduce_arg_types_impl(args[_name], args[_index|42]); | |
1660 | } | |
1661 | </pre> | |
1662 | <!-- @example.prepend(''' | |
1663 | #include <boost/parameter.hpp> | |
1664 | #include <cassert>''') --> | |
1665 | <!-- @example.append(''' | |
1666 | int a1 = deduce_arg_types((_name = "foo")); | |
1667 | int a2 = deduce_arg_types((_name = "foo", _index = 3)); | |
1668 | ||
1669 | int main() | |
1670 | { | |
1671 | assert(a1 == 42); | |
1672 | assert(a2 == 3); | |
1673 | }''') --> | |
1674 | <!-- @test('run') --> | |
1675 | <p>Occasionally one needs to deduce argument types without an extra | |
1676 | layer of function call. For example, suppose we wanted to return | |
1677 | twice the value of the <tt class="docutils literal">index</tt> parameter? In that | |
1678 | case we can use the <tt class="docutils literal">value_type< … ></tt> metafunction introduced | |
1679 | <a class="reference internal" href="#binding-intro">earlier</a>:</p> | |
1680 | <pre class="literal-block"> | |
1681 | BOOST_PARAMETER_NAME(index) | |
1682 | ||
1683 | template <class ArgumentPack> | |
1684 | typename parameter::value_type<ArgumentPack, tag::index, int>::type | |
1685 | twice_index(ArgumentPack const& args) | |
1686 | { | |
1687 | return 2 * args[_index|42]; | |
1688 | } | |
1689 | ||
1690 | int six = twice_index(_index = 3); | |
1691 | </pre> | |
1692 | <!-- @example.prepend(''' | |
1693 | #include <boost/parameter.hpp> | |
1694 | #include <boost/type_traits/remove_reference.hpp> | |
1695 | #include <cassert> | |
1696 | ||
1697 | namespace parameter = boost::parameter; | |
1698 | ''') --> | |
1699 | <!-- @example.append(''' | |
1700 | int main() | |
1701 | { | |
1702 | assert(six == 6); | |
1703 | }''') --> | |
1704 | <!-- @test('run', howmany='all') --> | |
1705 | <p>Note that if we had used <tt class="docutils literal">binding< … ></tt> rather than <tt class="docutils literal">value_type< … | |
1706 | ></tt>, we would end up returning a reference to the temporary created in | |
1707 | the <tt class="docutils literal">2 * …</tt> expression.</p> | |
1708 | </div> | |
1709 | <div class="section" id="lazy-default-computation"> | |
1710 | <h3>3.2.3 Lazy Default Computation</h3> | |
1711 | <p>When a default value is expensive to compute, it would be | |
1712 | preferable to avoid it until we're sure it's absolutely necessary. | |
1713 | <tt class="docutils literal">BOOST_PARAMETER_FUNCTION</tt> takes care of that problem for us, but | |
1714 | when using <span class="concept">ArgumentPack</span>s explicitly, we need a tool other than | |
1715 | <tt class="docutils literal">operator|</tt>:</p> | |
1716 | <pre class="literal-block"> | |
1717 | BOOST_PARAMETER_NAME(s1) | |
1718 | BOOST_PARAMETER_NAME(s2) | |
1719 | BOOST_PARAMETER_NAME(s3) | |
1720 | ||
1721 | template <class ArgumentPack> | |
1722 | std::string f(ArgumentPack const& args) | |
1723 | { | |
1724 | std::string const& s1 = args[_s1]; | |
1725 | std::string const& s2 = args[_s2]; | |
1726 | typename parameter::binding< | |
1727 | ArgumentPack,tag::s3,std::string | |
1728 | >::type s3 = args[_s3|(s1+s2)]; // always constructs s1+s2 | |
1729 | return s3; | |
1730 | } | |
1731 | ||
1732 | std::string x = f((_s1="hello,", _s2=" world", _s3="hi world")); | |
1733 | </pre> | |
1734 | <!-- @example.prepend(''' | |
1735 | #include <boost/parameter.hpp> | |
1736 | #include <string> | |
1737 | ||
1738 | namespace parameter = boost::parameter;''') --> | |
1739 | <!-- @example.append(''' | |
1740 | int main() | |
1741 | {}''') --> | |
1742 | <!-- @test('run') --> | |
1743 | <p>In the example above, the string <tt class="docutils literal">"hello, world"</tt> is constructed | |
1744 | despite the fact that the user passed us a value for <tt class="docutils literal">s3</tt>. To | |
1745 | remedy that, we can compute the default value <em>lazily</em> (that is, | |
1746 | only on demand), by using <tt class="docutils literal"><span class="pre">boost::bind()</span></tt> to create a function | |
1747 | object.</p> | |
1748 | <!-- danielw: I'm leaving the text below in the source, because we might --> | |
1749 | <!-- want to change back to it after 1.34, and if I remove it now we --> | |
1750 | <!-- might forget about it. --> | |
1751 | <!-- by combining the logical-or (“``||``”) operator --> | |
1752 | <!-- with a function object built by the Boost Lambda_ library: [#bind]_ --> | |
1753 | <pre class="literal-block"> | |
1754 | typename parameter::binding< | |
1755 | ArgumentPack, <a class="reference external" href="tag::s3">tag::s3</a>, std::string | |
1756 | >::type s3 = args[_s3 | |
1757 | <strong>|| boost::bind(std::plus<std::string>(), boost::ref(s1), boost::ref(s2))</strong> ]; | |
1758 | </pre> | |
1759 | <!-- @example.prepend(''' | |
1760 | #include <boost/bind.hpp> | |
1761 | #include <boost/ref.hpp> | |
1762 | #include <boost/parameter.hpp> | |
1763 | #include <string> | |
1764 | #include <functional> | |
1765 | ||
1766 | namespace parameter = boost::parameter; | |
1767 | ||
1768 | BOOST_PARAMETER_NAME(s1) | |
1769 | BOOST_PARAMETER_NAME(s2) | |
1770 | BOOST_PARAMETER_NAME(s3) | |
1771 | ||
1772 | template <class ArgumentPack> | |
1773 | std::string f(ArgumentPack const& args) | |
1774 | { | |
1775 | std::string const& s1 = args[_s1]; | |
1776 | std::string const& s2 = args[_s2];''') --> | |
1777 | <!-- @example.append(''' | |
1778 | return s3; | |
1779 | } | |
1780 | ||
1781 | std::string x = f((_s1="hello,", _s2=" world", _s3="hi world")); | |
1782 | ||
1783 | int main() | |
1784 | {}''') --> | |
1785 | <!-- @test('run') --> | |
1786 | <!-- .. _Lambda: ../../../lambda/index.html --> | |
1787 | <div class="sidebar"> | |
1788 | <p class="first sidebar-title">Mnemonics</p> | |
1789 | <p class="last">To remember the difference between <tt class="docutils literal">|</tt> and <tt class="docutils literal">||</tt>, recall that | |
1790 | <tt class="docutils literal">||</tt> normally uses short-circuit evaluation: its second | |
1791 | argument is only evaluated if its first argument is <tt class="docutils literal">false</tt>. | |
1792 | Similarly, in <tt class="docutils literal"><span class="pre">color_map[param||f]</span></tt>, <tt class="docutils literal">f</tt> is only invoked if | |
1793 | no <tt class="docutils literal">color_map</tt> argument was supplied.</p> | |
1794 | </div> | |
1795 | <p>The expression <tt class="docutils literal"><span class="pre">bind(std::plus<std::string>(),</span> ref(s1), ref(s2))</tt> yields | |
1796 | a <em>function object</em> that, when invoked, adds the two strings together. | |
1797 | That function will only be invoked if no <tt class="docutils literal">s3</tt> argument is supplied by | |
1798 | the caller.</p> | |
1799 | <!-- The expression ``lambda::var(s1)+lambda::var(s2)`` yields a --> | |
1800 | <!-- *function object* that, when invoked, adds the two strings --> | |
1801 | <!-- together. That function will only be invoked if no ``s3`` argument --> | |
1802 | <!-- is supplied by the caller. --> | |
1803 | </div> | |
1804 | </div> | |
1805 | </div> | |
1806 | <div class="section" id="best-practices"> | |
1807 | <h1><a class="toc-backref" href="#id34">4 Best Practices</a></h1> | |
1808 | <p>By now you should have a fairly good idea of how to use the | |
1809 | Parameter library. This section points out a few more-marginal | |
1810 | issues that will help you use the library more effectively.</p> | |
1811 | <div class="section" id="keyword-naming"> | |
1812 | <h2><a class="toc-backref" href="#id35">4.1 Keyword Naming</a></h2> | |
1813 | <p><tt class="docutils literal">BOOST_PARAMETER_NAME</tt> prepends a leading underscore to the names | |
1814 | of all our keyword objects in order to avoid the following | |
1815 | usually-silent bug:</p> | |
1816 | <pre class="literal-block"> | |
1817 | namespace people | |
1818 | { | |
1819 | namespace tag { struct name; struct age; } | |
1820 | ||
1821 | namespace // unnamed | |
1822 | { | |
1823 | boost::parameter::keyword<tag::name>& <strong>name</strong> | |
1824 | = boost::parameter::keyword<tag::name>::instance; | |
1825 | boost::parameter::keyword<tag::age>& <strong>age</strong> | |
1826 | = boost::parameter::keyword<tag::age>::instance; | |
1827 | } | |
1828 | ||
1829 | BOOST_PARAMETER_FUNCTION( | |
1830 | (void), g, tag, (optional (name, *, "bob")(age, *, 42))) | |
1831 | { | |
1832 | std::cout << name << ":" << age; | |
1833 | } | |
1834 | ||
1835 | void f(int age) | |
1836 | { | |
1837 | <span class="vellipsis"> . | |
1838 | . | |
1839 | . | |
1840 | </span> | |
1841 | g(<strong>age</strong> = 3); // whoops! | |
1842 | } | |
1843 | } | |
1844 | </pre> | |
1845 | <!-- @ignore() --> | |
1846 | <p>Although in the case above, the user was trying to pass the value | |
1847 | <tt class="docutils literal">3</tt> as the <tt class="docutils literal">age</tt> parameter to <tt class="docutils literal">g</tt>, what happened instead | |
1848 | was that <tt class="docutils literal">f</tt>'s <tt class="docutils literal">age</tt> argument got reassigned the value 3, | |
1849 | and was then passed as a positional argument to <tt class="docutils literal">g</tt>. Since | |
1850 | <tt class="docutils literal">g</tt>'s first positional parameter is <tt class="docutils literal">name</tt>, the default value | |
1851 | for <tt class="docutils literal">age</tt> is used, and g prints <tt class="docutils literal">3:42</tt>. Our leading | |
1852 | underscore naming convention that makes this problem less likely | |
1853 | to occur.</p> | |
1854 | <p>In this particular case, the problem could have been detected if | |
1855 | f's <tt class="docutils literal">age</tt> parameter had been made <tt class="docutils literal">const</tt>, which is always a | |
1856 | good idea whenever possible. Finally, we recommend that you use | |
1857 | an enclosing namespace for all your code, but particularly for | |
1858 | names with leading underscores. If we were to leave out the | |
1859 | <tt class="docutils literal">people</tt> namespace above, names in the global namespace | |
1860 | beginning with leading underscores—which are reserved to your C++ | |
1861 | compiler—might become irretrievably ambiguous with those in our | |
1862 | unnamed namespace.</p> | |
1863 | </div> | |
1864 | <div class="section" id="namespaces"> | |
1865 | <h2><a class="toc-backref" href="#id36">4.2 Namespaces</a></h2> | |
1866 | <p>In our examples we've always declared keyword objects in (an | |
1867 | unnamed namespace within) the same namespace as the | |
1868 | Boost.Parameter-enabled functions using those keywords:</p> | |
1869 | <pre class="literal-block"> | |
1870 | namespace lib | |
1871 | { | |
1872 | <strong>BOOST_PARAMETER_NAME(name) | |
1873 | BOOST_PARAMETER_NAME(index)</strong> | |
1874 | ||
1875 | BOOST_PARAMETER_FUNCTION( | |
1876 | (int), f, tag, | |
1877 | (optional (name,*,"bob")(index,(int),1)) | |
1878 | ) | |
1879 | { | |
1880 | std::cout << name << ":" << index << std::endl; | |
1881 | return index; | |
1882 | } | |
1883 | } | |
1884 | </pre> | |
1885 | <!-- @example.prepend(''' | |
1886 | #include <boost/parameter.hpp> | |
1887 | #include <iostream>''') --> | |
1888 | <!-- @namespace_setup = str(example) --> | |
1889 | <!-- @ignore() --> | |
1890 | <p>Users of these functions have a few choices:</p> | |
1891 | <ol class="arabic simple"> | |
1892 | <li>Full qualification:</li> | |
1893 | </ol> | |
1894 | <blockquote> | |
1895 | <pre class="literal-block"> | |
1896 | int x = <strong>lib::</strong>f(<strong>lib::</strong>_name = "jill", <strong>lib::</strong>_index = 1); | |
1897 | </pre> | |
1898 | <p>This approach is more verbose than many users would like.</p> | |
1899 | </blockquote> | |
1900 | <!-- @example.prepend(namespace_setup) --> | |
1901 | <!-- @example.append('int main() {}') --> | |
1902 | <!-- @test('run') --> | |
1903 | <ol class="arabic simple" start="2"> | |
1904 | <li>Make keyword objects available through | |
1905 | <em>using-declarations</em>:</li> | |
1906 | </ol> | |
1907 | <blockquote> | |
1908 | <pre class="literal-block"> | |
1909 | <strong>using lib::_name; | |
1910 | using lib::_index;</strong> | |
1911 | ||
1912 | int x = lib::f(_name = "jill", _index = 1); | |
1913 | </pre> | |
1914 | <p>This version is much better at the actual call site, but the | |
1915 | <em>using-declarations</em> themselves can be verbose and hard-to | |
1916 | manage.</p> | |
1917 | </blockquote> | |
1918 | <!-- @example.prepend(namespace_setup) --> | |
1919 | <!-- @example.append('int main() {}') --> | |
1920 | <!-- @test('run') --> | |
1921 | <ol class="arabic simple" start="3"> | |
1922 | <li>Bring in the entire namespace with a <em>using-directive</em>:</li> | |
1923 | </ol> | |
1924 | <blockquote> | |
1925 | <pre class="literal-block"> | |
1926 | <strong>using namespace lib;</strong> | |
1927 | int x = <strong>f</strong>(_name = "jill", _index = 3); | |
1928 | </pre> | |
1929 | <p>This option is convenient, but it indiscriminately makes the | |
1930 | <em>entire</em> contents of <tt class="docutils literal">lib</tt> available without qualification.</p> | |
1931 | </blockquote> | |
1932 | <!-- @example.prepend(namespace_setup) --> | |
1933 | <!-- @example.append('int main() {}') --> | |
1934 | <!-- @test('run') --> | |
1935 | <p>If we add an additional namespace around keyword declarations, | |
1936 | though, we can give users more control:</p> | |
1937 | <pre class="literal-block"> | |
1938 | namespace lib | |
1939 | { | |
1940 | <strong>namespace keywords | |
1941 | {</strong> | |
1942 | BOOST_PARAMETER_NAME(name) | |
1943 | BOOST_PARAMETER_NAME(index) | |
1944 | <strong>}</strong> | |
1945 | ||
1946 | BOOST_PARAMETER_FUNCTION( | |
1947 | (int), f, <strong>keywords::</strong>tag, | |
1948 | (optional (name,*,"bob")(index,(int),1)) | |
1949 | ) | |
1950 | { | |
1951 | std::cout << name << ":" << index << std::endl; | |
1952 | return index; | |
1953 | } | |
1954 | } | |
1955 | </pre> | |
1956 | <!-- @example.prepend(''' | |
1957 | #include <boost/parameter.hpp> | |
1958 | #include <iostream>''') --> | |
1959 | <p>Now users need only a single <em>using-directive</em> to bring in just the | |
1960 | names of all keywords associated with <tt class="docutils literal">lib</tt>:</p> | |
1961 | <pre class="literal-block"> | |
1962 | <strong>using namespace lib::keywords;</strong> | |
1963 | int y = lib::f(_name = "bob", _index = 2); | |
1964 | </pre> | |
1965 | <!-- @example.append('int main() {}') --> | |
1966 | <!-- @test('run', howmany='all') --> | |
1967 | </div> | |
1968 | <div class="section" id="documentation"> | |
1969 | <h2><a class="toc-backref" href="#id37">4.3 Documentation</a></h2> | |
1970 | <p>The interface idioms enabled by Boost.Parameter are completely new | |
1971 | (to C++), and as such are not served by pre-existing documentation | |
1972 | conventions.</p> | |
1973 | <div class="note"> | |
1974 | <p class="first admonition-title">Note</p> | |
1975 | <p class="last">This space is empty because we haven't settled on any | |
1976 | best practices yet. We'd be very pleased to link to your | |
1977 | documentation if you've got a style that you think is worth | |
1978 | sharing.</p> | |
1979 | </div> | |
1980 | </div> | |
1981 | </div> | |
1982 | <div class="section" id="portability-considerations"> | |
1983 | <h1><a class="toc-backref" href="#id38">5 Portability Considerations</a></h1> | |
1984 | <p>Use the <a class="reference external" href="http://www.boost.org/regression/release/user/parameter.html">regression test results</a> for the latest Boost release of | |
1985 | the Parameter library to see how it fares on your favorite | |
1986 | compiler. Additionally, you may need to be aware of the following | |
1987 | issues and workarounds for particular compilers.</p> | |
1988 | <div class="section" id="no-sfinae-support"> | |
1989 | <h2><a class="toc-backref" href="#id39">5.1 No SFINAE Support</a></h2> | |
1990 | <p>Some older compilers don't support SFINAE. If your compiler meets | |
1991 | that criterion, then Boost headers will <tt class="docutils literal">#define</tt> the preprocessor | |
1992 | symbol <tt class="docutils literal">BOOST_NO_SFINAE</tt>, and parameter-enabled functions won't be | |
1993 | removed from the overload set based on their signatures.</p> | |
1994 | </div> | |
1995 | <div class="section" id="no-support-for-result-of"> | |
1996 | <h2>5.2 No Support for <a class="reference external" href="../../../utility/utility.htm#result_of"><tt class="docutils literal">result_of</tt></a></h2> | |
1997 | <p><a class="reference internal" href="#lazy-default-computation">Lazy default computation</a> relies on the <tt class="docutils literal">result_of</tt> class | |
1998 | template to compute the types of default arguments given the type | |
1999 | of the function object that constructs them. On compilers that | |
2000 | don't support <tt class="docutils literal">result_of</tt>, <tt class="docutils literal">BOOST_NO_RESULT_OF</tt> will be | |
2001 | <tt class="docutils literal">#define</tt>d, and the compiler will expect the function object to | |
2002 | contain a nested type name, <tt class="docutils literal">result_type</tt>, that indicates its | |
2003 | return type when invoked without arguments. To use an ordinary | |
2004 | function as a default generator on those compilers, you'll need to | |
2005 | wrap it in a class that provides <tt class="docutils literal">result_type</tt> as a <tt class="docutils literal">typedef</tt> | |
2006 | and invokes the function via its <tt class="docutils literal">operator()</tt>.</p> | |
2007 | <!-- Can't Declare |ParameterSpec| via ``typedef`` | |
2008 | ============================================= | |
2009 | ||
2010 | In principle you can declare a |ParameterSpec| as a ``typedef`` | |
2011 | for a specialization of ``parameters<…>``, but Microsoft Visual C++ | |
2012 | 6.x has been seen to choke on that usage. The workaround is to use | |
2013 | inheritance and declare your |ParameterSpec| as a class: | |
2014 | ||
2015 | .. parsed-literal:: | |
2016 | ||
2017 | **struct dfs_parameters | |
2018 | :** parameter::parameters< | |
2019 | tag::graph, tag::visitor, tag::root_vertex | |
2020 | , tag::index_map, tag::color_map | |
2021 | > **{};** | |
2022 | ||
2023 | ||
2024 | Default Arguments Unsupported on Nested Templates | |
2025 | ================================================= | |
2026 | ||
2027 | As of this writing, Borland compilers don't support the use of | |
2028 | default template arguments on member class templates. As a result, | |
2029 | you have to supply ``BOOST_PARAMETER_MAX_ARITY`` arguments to every | |
2030 | use of ``parameters<…>::match``. Since the actual defaults used | |
2031 | are unspecified, the workaround is to use | |
2032 | |BOOST_PARAMETER_MATCH|_ to declare default arguments for SFINAE. | |
2033 | ||
2034 | .. |BOOST_PARAMETER_MATCH| replace:: ``BOOST_PARAMETER_MATCH`` --> | |
2035 | </div> | |
2036 | <div class="section" id="compiler-can-t-see-references-in-unnamed-namespace"> | |
2037 | <h2><a class="toc-backref" href="#id41">5.3 Compiler Can't See References In Unnamed Namespace</a></h2> | |
2038 | <p>If you use Microsoft Visual C++ 6.x, you may find that the compiler | |
2039 | has trouble finding your keyword objects. This problem has been | |
2040 | observed, but only on this one compiler, and it disappeared as the | |
2041 | test code evolved, so we suggest you use it only as a last resort | |
2042 | rather than as a preventative measure. The solution is to add | |
2043 | <em>using-declarations</em> to force the names to be available in the | |
2044 | enclosing namespace without qualification:</p> | |
2045 | <pre class="literal-block"> | |
2046 | namespace graphs | |
2047 | { | |
2048 | using graphs::graph; | |
2049 | using graphs::visitor; | |
2050 | using graphs::root_vertex; | |
2051 | using graphs::index_map; | |
2052 | using graphs::color_map; | |
2053 | } | |
2054 | </pre> | |
2055 | </div> | |
2056 | </div> | |
2057 | <div class="section" id="python-binding"> | |
2058 | <h1><a class="toc-backref" href="#id42">6 Python Binding</a></h1> | |
2059 | <p>Follow <a class="reference external" href="python.html">this link</a> for documentation on how to expose | |
2060 | Boost.Parameter-enabled functions to Python with <a class="reference external" href="../../../python/doc/index.html">Boost.Python</a>.</p> | |
2061 | </div> | |
2062 | <div class="section" id="reference"> | |
2063 | <h1><a class="toc-backref" href="#id43">7 Reference</a></h1> | |
2064 | <p>Follow <a class="reference external" href="reference.html">this link</a> to the Boost.Parameter reference | |
2065 | documentation.</p> | |
2066 | </div> | |
2067 | <div class="section" id="glossary"> | |
2068 | <h1><a class="toc-backref" href="#id44">8 Glossary</a></h1> | |
2069 | <table class="docutils field-list" frame="void" id="arguments" rules="none"> | |
2070 | <col class="field-name" /> | |
2071 | <col class="field-body" /> | |
2072 | <tbody valign="top"> | |
2073 | <tr class="field"><th class="field-name" colspan="2">Argument (or “actual argument”):</th></tr> | |
2074 | <tr><td> </td><td class="field-body">the value actually passed to a | |
2075 | function or class template</td> | |
2076 | </tr> | |
2077 | </tbody> | |
2078 | </table> | |
2079 | <table class="docutils field-list" frame="void" id="parameter" rules="none"> | |
2080 | <col class="field-name" /> | |
2081 | <col class="field-body" /> | |
2082 | <tbody valign="top"> | |
2083 | <tr class="field"><th class="field-name" colspan="2">Parameter (or “formal parameter”):</th></tr> | |
2084 | <tr><td> </td><td class="field-body"><p class="first">the name used to refer to an | |
2085 | argument within a function or class template. For example, the | |
2086 | value of <tt class="docutils literal">f</tt>'s <em>parameter</em> <tt class="docutils literal">x</tt> is given by the <em>argument</em> | |
2087 | <tt class="docutils literal">3</tt>:</p> | |
2088 | <pre class="last literal-block"> | |
2089 | int f(int x) { return x + 1 } | |
2090 | int y = f(3); | |
2091 | </pre> | |
2092 | </td> | |
2093 | </tr> | |
2094 | </tbody> | |
2095 | </table> | |
2096 | </div> | |
2097 | <div class="section" id="acknowledgements"> | |
2098 | <h1><a class="toc-backref" href="#id45">9 Acknowledgements</a></h1> | |
2099 | <p>The authors would like to thank all the Boosters who participated | |
2100 | in the review of this library and its documentation, most | |
2101 | especially our review manager, Doug Gregor.</p> | |
2102 | <hr class="docutils" /> | |
2103 | <table class="docutils footnote" frame="void" id="old-interface" rules="none"> | |
2104 | <colgroup><col class="label" /><col /></colgroup> | |
2105 | <tbody valign="top"> | |
2106 | <tr><td class="label"><a class="fn-backref" href="#id3">[1]</a></td><td>As of Boost 1.33.0 the Graph library was still | |
2107 | using an <a class="reference external" href="../../../graph/doc/bgl_named_params.html">older named parameter mechanism</a>, but there are | |
2108 | plans to change it to use Boost.Parameter (this library) in an | |
2109 | upcoming release, while keeping the old interface available for | |
2110 | backward-compatibility.</td></tr> | |
2111 | </tbody> | |
2112 | </table> | |
2113 | <table class="docutils footnote" frame="void" id="odr" rules="none"> | |
2114 | <colgroup><col class="label" /><col /></colgroup> | |
2115 | <tbody valign="top"> | |
2116 | <tr><td class="label"><a class="fn-backref" href="#id5">[2]</a></td><td>The <strong>One Definition Rule</strong> says that any given entity in | |
2117 | a C++ program must have the same definition in all translation | |
2118 | units (object files) that make up a program.</td></tr> | |
2119 | </tbody> | |
2120 | </table> | |
2121 | <table class="docutils footnote" frame="void" id="vertex-descriptor" rules="none"> | |
2122 | <colgroup><col class="label" /><col /></colgroup> | |
2123 | <tbody valign="top"> | |
2124 | <tr><td class="label">[3]</td><td>If you're not familiar with the Boost Graph | |
2125 | Library, don't worry about the meaning of any | |
2126 | Graph-library-specific details you encounter. In this case you | |
2127 | could replace all mentions of vertex descriptor types with | |
2128 | <tt class="docutils literal">int</tt> in the text, and your understanding of the Parameter | |
2129 | library wouldn't suffer.</td></tr> | |
2130 | </tbody> | |
2131 | </table> | |
2132 | <table class="docutils footnote" frame="void" id="conceptcpp" rules="none"> | |
2133 | <colgroup><col class="label" /><col /></colgroup> | |
2134 | <tbody valign="top"> | |
2135 | <tr><td class="label"><a class="fn-backref" href="#id7">[4]</a></td><td>This is a major motivation behind <a class="reference external" href="http://www.generic-programming.org/software/ConceptGCC/">ConceptC++</a>.</td></tr> | |
2136 | </tbody> | |
2137 | </table> | |
2138 | <!-- .. [#bind] The Lambda library is known not to work on `some --> | |
2139 | <!-- less-conformant compilers`__. When using one of those you could --> | |
2140 | <!-- use `Boost.Bind`_ to generate the function object:: --> | |
2141 | <!-- boost::bind(std::plus<std::string>(),s1,s2) --> | |
2142 | <table class="docutils footnote" frame="void" id="is-keyword-expression" rules="none"> | |
2143 | <colgroup><col class="label" /><col /></colgroup> | |
2144 | <tbody valign="top"> | |
2145 | <tr><td class="label">[5]</td><td><em>(<a class="fn-backref" href="#id13">1</a>, <a class="fn-backref" href="#id14">2</a>)</em> Here we're assuming there's a predicate | |
2146 | metafunction <tt class="docutils literal">is_keyword_expression</tt> that can be used to | |
2147 | identify models of Boost.Python's KeywordExpression concept.</td></tr> | |
2148 | </tbody> | |
2149 | </table> | |
2150 | <!-- .. __ http://www.boost.org/regression/release/user/lambda.html --> | |
2151 | <table class="docutils footnote" frame="void" id="using" rules="none"> | |
2152 | <colgroup><col class="label" /><col /></colgroup> | |
2153 | <tbody valign="top"> | |
2154 | <tr><td class="label"><a class="fn-backref" href="#id8">[6]</a></td><td><p class="first">You can always give the illusion that the function | |
2155 | lives in an outer namespace by applying a <em>using-declaration</em>:</p> | |
2156 | <pre class="last literal-block"> | |
2157 | namespace foo_overloads | |
2158 | { | |
2159 | // foo declarations here | |
2160 | void foo() { ... } | |
2161 | ... | |
2162 | } | |
2163 | using foo_overloads::foo; | |
2164 | ||
2165 | This technique for avoiding unintentional argument-dependent | |
2166 | lookup is due to Herb Sutter. | |
2167 | </pre> | |
2168 | </td></tr> | |
2169 | </tbody> | |
2170 | </table> | |
2171 | <table class="docutils footnote" frame="void" id="sfinae" rules="none"> | |
2172 | <colgroup><col class="label" /><col /></colgroup> | |
2173 | <tbody valign="top"> | |
2174 | <tr><td class="label">[7]</td><td>This capability depends on your compiler's support for SFINAE. | |
2175 | <strong>SFINAE</strong>: <strong>S</strong>ubstitution <strong>F</strong>ailure <strong>I</strong>s | |
2176 | <strong>N</strong>ot <strong>A</strong>n <strong>E</strong> rror. If type substitution during the | |
2177 | instantiation of a function template results in an invalid type, | |
2178 | no compilation error is emitted; instead the overload is removed | |
2179 | from the overload set. By producing an invalid type in the | |
2180 | function signature depending on the result of some condition, | |
2181 | we can decide whether or not an overload is considered during overload | |
2182 | resolution. The technique is formalized in | |
2183 | the <a class="reference external" href="../../../utility/enable_if.html"><tt class="docutils literal">enable_if</tt></a> utility. Most recent compilers support SFINAE; | |
2184 | on compilers that don't support it, the Boost config library | |
2185 | will <tt class="docutils literal">#define</tt> the symbol <tt class="docutils literal">BOOST_NO_SFINAE</tt>. | |
2186 | See | |
2187 | <a class="reference external" href="http://www.semantics.org/once_weakly/w02_SFINAE.pdf">http://www.semantics.org/once_weakly/w02_SFINAE.pdf</a> for more | |
2188 | information on SFINAE.</td></tr> | |
2189 | </tbody> | |
2190 | </table> | |
2191 | </div> | |
2192 | </div> | |
2193 | <div class="footer"> | |
2194 | <hr class="footer" /> | |
2195 | Generated on: 2011-11-08 21:40 UTC. | |
2196 | Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source. | |
2197 | ||
2198 | </div> | |
2199 | </body> | |
2200 | </html> |