-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathtag_metafunctions.html
More file actions
295 lines (257 loc) · 18.4 KB
/
tag_metafunctions.html
File metadata and controls
295 lines (257 loc) · 18.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Tag metafunctions — cpp-netlib v0.8 documentation</title>
<link rel="stylesheet" href="_static/cpp-netlib.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '',
VERSION: '0.8',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="cpp-netlib v0.8 documentation" href="index.html" />
<link rel="up" title="Techniques" href="techniques.html" />
<link rel="next" title="Directives" href="directives.html" />
<link rel="prev" title="Techniques" href="techniques.html" />
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-19815738-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div class="document">
<div id="custom-doc" class="yui-t4">
<div id="hd">
<h1><a href="index.html">cpp-netlib v0.8 documentation</a></h1>
<div class="nav">
« <a href="techniques.html" title="Techniques">previous</a>
|
<a href="techniques.html" title="Techniques" accesskey="U">up</a>
|
<a href="directives.html" title="Directives">next</a> »</div>
</div>
<div id="bd">
<div id="yui-main">
<div class="yui-b">
<div class="yui-g" id="tag_metafunctions">
<div class="section" id="tag-metafunctions">
<h1>Tag metafunctions<a class="headerlink" href="#tag-metafunctions" title="Permalink to this headline">¶</a></h1>
<p>Sometimes you want to vary a function or a type’s behavior based on a
static parameter. In the <tt class="xref py py-mod docutils literal"><span class="pre">cpp-netlib</span></tt> there are a number of
things you might want to change based on some such parameter – like
what the underlying string type should be and how large a buffer
should be, among other things. The primary way to define this in a
header-only manner is to use tag-based metafunctions.</p>
<p>The skeleton of the approach is based on a similar technique for
defining type traits. In the <tt class="xref py py-mod docutils literal"><span class="pre">cpp-netlib</span></tt> however the type traits
are defined on opaque tag types which serve to associate results to a
family of metafunctions.</p>
<div class="section" id="template-specialization">
<h2>Template Specialization<a class="headerlink" href="#template-specialization" title="Permalink to this headline">¶</a></h2>
<p>To illustrate this point, let’s define a tag <tt class="docutils literal"><span class="pre">default_</span></tt> which we use
to denote the default implementation of a certain type <tt class="docutils literal"><span class="pre">foo</span></tt>. For
instance we decide that the default string type we will use for
<tt class="docutils literal"><span class="pre">default_</span></tt> tagged <tt class="docutils literal"><span class="pre">foo</span></tt> specializations will be an
<tt class="docutils literal"><span class="pre">std::string</span></tt>.</p>
<p>In the <tt class="xref py py-mod docutils literal"><span class="pre">cpp-netlib</span></tt> this is done by defining a <tt class="docutils literal"><span class="pre">string</span></tt>
metafunction type that is specialized on the tag <tt class="docutils literal"><span class="pre">default_</span></tt> whose
nested <tt class="docutils literal"><span class="pre">type</span></tt> result is the type <tt class="docutils literal"><span class="pre">std::string</span></tt>. In code this would
translate to:</p>
<div class="highlight-c++"><div class="highlight"><pre><span class="k">template</span> <span class="o"><</span><span class="k">class</span> <span class="nc">Tag</span><span class="o">></span>
<span class="k">struct</span> <span class="n">string</span> <span class="p">{</span>
<span class="k">typedef</span> <span class="kt">void</span> <span class="n">type</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">struct</span> <span class="n">default_</span><span class="p">;</span>
<span class="k">template</span> <span class="o"><></span>
<span class="k">struct</span> <span class="n">string</span><span class="o"><</span><span class="n">default_</span><span class="o">></span> <span class="p">{</span>
<span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">type</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
</div>
<div class="section" id="template-metaprogramming">
<h2>Template Metaprogramming<a class="headerlink" href="#template-metaprogramming" title="Permalink to this headline">¶</a></h2>
<p>Starting with version 0.7, the tag dispatch mechanism changed slightly to use
<a class="reference external" href="http://www.boost.org/libs/mpl/index.html">Boost.MPL</a>. The idea is still the same, although we can get a little smarter
than just using template specializations. Instead of just defining an opaque
type <tt class="docutils literal"><span class="pre">default_</span></tt>, we use the Boost.MPL equivalent of a vector to define which
root types of properties this <tt class="docutils literal"><span class="pre">default_</span></tt> tag supports. The idea is to make the
opaque type <tt class="docutils literal"><span class="pre">default_</span></tt> inherit property tags which the library supports
internally as definite extension points.</p>
<p>Our definition of the <tt class="docutils literal"><span class="pre">default_</span></tt> tag will then look something like the
following:</p>
<div class="highlight-c++"><div class="highlight"><pre><span class="k">typedef</span> <span class="n">mpl</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="n">default_string</span><span class="o">></span> <span class="n">default_tags</span><span class="p">;</span>
<span class="k">template</span> <span class="o"><</span><span class="k">class</span> <span class="nc">Tag</span><span class="o">></span>
<span class="k">struct</span> <span class="n">components</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">mpl</span><span class="o">::</span><span class="n">inherit_linearly</span><span class="o"><</span>
<span class="n">default_tags</span><span class="p">,</span>
<span class="n">mpl</span><span class="o">::</span><span class="n">inherit</span><span class="o"><</span><span class="n">mpl</span><span class="o">::</span><span class="n">placeholders</span><span class="o">::</span><span class="n">_1</span><span class="p">,</span> <span class="n">mpl</span><span class="o">::</span><span class="n">placeholders</span><span class="o">::</span><span class="n">_2</span><span class="o">></span>
<span class="o">>::</span><span class="n">type</span> <span class="n">default_</span><span class="p">;</span>
<span class="k">template</span> <span class="o"><</span><span class="k">class</span> <span class="nc">Tag</span><span class="o">></span>
<span class="k">struct</span> <span class="n">components</span><span class="o"><</span><span class="n">default_</span><span class="o">></span> <span class="p">{</span>
<span class="k">typedef</span> <span class="n">default_tags</span> <span class="n">type</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>In the above listing, <tt class="docutils literal"><span class="pre">default_string</span></tt> is what we call a “root” tag which is
meant to be combined with other “root” tags to form composite tags. In this case
our composite tag is the tag <tt class="docutils literal"><span class="pre">default_</span></tt>. There are a number of these “root”
tags that <tt class="xref py py-mod docutils literal"><span class="pre">cpp-netlib</span></tt> provides. These are in the namespace
<tt class="docutils literal"><span class="pre">boost::network::tags</span></tt> and are defined in <tt class="docutils literal"><span class="pre">boost/network/tags.hpp</span></tt>.</p>
<p>Using this technique we change slightly our definition of the <tt class="docutils literal"><span class="pre">string</span></tt>
metafunction class into this:</p>
<div class="highlight-c++"><div class="highlight"><pre><span class="k">template</span> <span class="o"><</span><span class="k">class</span> <span class="nc">Tag</span><span class="o">></span>
<span class="k">struct</span> <span class="n">unsupported_tag</span><span class="p">;</span>
<span class="k">template</span> <span class="o"><</span><span class="k">class</span> <span class="nc">Tag</span><span class="o">></span>
<span class="k">struct</span> <span class="n">string</span> <span class="o">:</span>
<span class="n">mpl</span><span class="o">::</span><span class="n">if_</span><span class="o"><</span>
<span class="n">is_base_of</span><span class="o"><</span>
<span class="n">tags</span><span class="o">::</span><span class="n">default_string</span><span class="p">,</span>
<span class="n">Tag</span>
<span class="o">></span><span class="p">,</span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span>
<span class="n">unsupported_tag</span><span class="o"><</span><span class="n">Tag</span><span class="o">></span>
<span class="o">></span>
<span class="p">{};</span>
</pre></div>
</div>
<p>Notice that we don’t have the typedef for <tt class="docutils literal"><span class="pre">type</span></tt> in the body of <tt class="docutils literal"><span class="pre">string</span></tt>
anymore, but we do inherit from <tt class="docutils literal"><span class="pre">mpl::if_</span></tt>. Since <tt class="docutils literal"><span class="pre">mpl::if_</span></tt> is a template
metafunction itself, it contains a definition of the resulting <tt class="docutils literal"><span class="pre">type</span></tt> which
<tt class="docutils literal"><span class="pre">string</span></tt> inherits.</p>
<p>You can see the real definition of the <tt class="docutils literal"><span class="pre">string</span></tt> metafunction in
<tt class="docutils literal"><span class="pre">boost/network/traits/string.hpp</span></tt>.</p>
</div>
<div class="section" id="using-tags">
<h2>Using Tags<a class="headerlink" href="#using-tags" title="Permalink to this headline">¶</a></h2>
<p>Once we have the defined tag, we can then use this in the definition of our
types. In the definition of the type <tt class="docutils literal"><span class="pre">foo</span></tt> we use this type function
<tt class="docutils literal"><span class="pre">string</span></tt> and pass the tag type parameter to determine what to use as
the string type in the context of the type <tt class="docutils literal"><span class="pre">foo</span></tt>. In code this would
translate into:</p>
<div class="highlight-c++"><div class="highlight"><pre><span class="k">template</span> <span class="o"><</span><span class="k">class</span> <span class="nc">Tag</span><span class="o">></span>
<span class="k">struct</span> <span class="n">foo</span> <span class="p">{</span>
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">string</span><span class="o"><</span><span class="n">Tag</span><span class="o">>::</span><span class="n">type</span> <span class="n">string_type</span><span class="p">;</span>
<span class="c1">// .. use string_type where you need a string.</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Using this approach we can support different types of strings for
different tags on the type <tt class="docutils literal"><span class="pre">foo</span></tt>. In case we want to use a different
type of string for the tag <tt class="docutils literal"><span class="pre">default_</span></tt> we only change the
composition of the <tt class="docutils literal"><span class="pre">string_tags</span></tt> MPL vector. For example, in <tt class="xref py py-mod docutils literal"><span class="pre">cpp-netlib</span></tt>
there is a root tag <tt class="docutils literal"><span class="pre">default_wstring</span></tt> which causes the <tt class="docutils literal"><span class="pre">string</span></tt> metafunction
to define <tt class="docutils literal"><span class="pre">std::wstring</span></tt> as the resulting type.</p>
<p>The approach also allows for the control of the structure and features
of types like <tt class="docutils literal"><span class="pre">foo</span></tt> based on the specialization of the tag. Whole
type function families can be defined on tags where they are supported
and ignored in cases where they are not.</p>
<p>To illustrate let’s define a new tag <tt class="docutils literal"><span class="pre">swappable</span></tt>. Given the above
definition of <tt class="docutils literal"><span class="pre">foo</span></tt>, we want to make the <tt class="docutils literal"><span class="pre">swappable</span></tt>-tagged
<tt class="docutils literal"><span class="pre">foo</span></tt> define a <tt class="docutils literal"><span class="pre">swap</span></tt> function that extends the original
<tt class="docutils literal"><span class="pre">default_</span></tt>-tagged <tt class="docutils literal"><span class="pre">foo</span></tt>. In code this would look like:</p>
<div class="highlight-c++"><div class="highlight"><pre><span class="k">struct</span> <span class="n">swappable</span><span class="p">;</span>
<span class="k">template</span> <span class="o"><></span>
<span class="k">struct</span> <span class="n">foo</span><span class="o"><</span><span class="n">swappable</span><span class="o">></span> <span class="o">:</span> <span class="n">foo</span><span class="o"><</span><span class="n">default_</span><span class="o">></span> <span class="p">{</span>
<span class="kt">void</span> <span class="n">swap</span><span class="p">(</span><span class="n">foo</span><span class="o"><</span><span class="n">swappable</span><span class="o">></span> <span class="o">&</span> <span class="n">other</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// ...</span>
<span class="p">}</span>
<span class="p">};</span>
</pre></div>
</div>
<p>We also for example want to enable an ADL-reachable <tt class="docutils literal"><span class="pre">swap</span></tt> function:</p>
<div class="highlight-c++"><div class="highlight"><pre><span class="k">struct</span> <span class="n">swappable</span><span class="p">;</span>
<span class="kr">inline</span>
<span class="kt">void</span> <span class="n">swap</span><span class="p">(</span><span class="n">foo</span><span class="o"><</span><span class="n">swappable</span><span class="o">></span> <span class="o">&</span> <span class="n">left</span><span class="p">,</span> <span class="n">foo</span><span class="o"><</span><span class="n">swappable</span><span class="o">></span> <span class="o">&</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span>
<span class="n">left</span><span class="p">.</span><span class="n">swap</span><span class="p">(</span><span class="n">right</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Overall what the tag-based definition approach allows is for static
definition of extension points that ensures type-safety and
invariants. This keeps the whole extension mechanism static and yet
flexible.</p>
</div>
</div>
</div>
</div>
</div>
<div class="yui-b" id="sidebar">
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Tag metafunctions</a><ul>
<li><a class="reference internal" href="#template-specialization">Template Specialization</a></li>
<li><a class="reference internal" href="#template-metaprogramming">Template Metaprogramming</a></li>
<li><a class="reference internal" href="#using-tags">Using Tags</a></li>
</ul>
</li>
</ul>
<h3>Browse</h3>
<ul>
<li>Prev: <a href="techniques.html">Techniques</a></li>
<li>Next: <a href="directives.html">Directives</a></li>
</ul>
<h3>You are here:</h3>
<ul>
<li>
<a href="index.html">cpp-netlib v0.8 documentation</a>
<ul><li><a href="techniques.html">Techniques</a>
<ul><li>Tag metafunctions</li></ul>
</li></ul>
</li>
</ul>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/tag_metafunctions.txt"
rel="nofollow">Show Source</a></li>
</ul>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" size="18" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
<p class="searchtip" style="font-size: 90%">
Enter search terms or a module, class or function name.
</p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
</div>
</div>
<div id="ft">
<div class="nav">
« <a href="techniques.html" title="Techniques">previous</a>
|
<a href="techniques.html" title="Techniques" accesskey="U">up</a>
|
<a href="directives.html" title="Directives">next</a> »</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
documentation automatically generated by <a href="http://sphinx.pocoo.org">Sphinx</a> | style mostly stolen from <a href="http://lettuce.it">lettuce.it</a>
</div>
</body>
</html>