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