-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathpolymorphism.html
189 lines (176 loc) · 12.1 KB
/
polymorphism.html
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
<!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>Static and dynamic polymorphism — cpp-netlib v0.10.0</title>
<link rel="stylesheet" href="../_static/pyramid.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.10.0',
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.10.0" href="../index.html" />
<link rel="up" title="Techniques" href="../techniques.html" />
<link rel="next" title="Project history" href="../history.html" />
<link rel="prev" title="Directives" href="directives.html" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&subset=latin" type="text/css" media="screen" charset="utf-8" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&subset=latin" type="text/css" media="screen" charset="utf-8" />
<!--[if lte IE 6]>
<link rel="stylesheet" href="../_static/ie6.css" type="text/css" media="screen" charset="utf-8" />
<![endif]-->
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../history.html" title="Project history"
accesskey="N">next</a></li>
<li class="right" >
<a href="directives.html" title="Directives"
accesskey="P">previous</a> |</li>
<li><a href="../contents.html">cpp-netlib v0.10.0</a> »</li>
<li><a href="../techniques.html" accesskey="U">Techniques</a> »</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="static-and-dynamic-polymorphism">
<h1>Static and dynamic polymorphism<a class="headerlink" href="#static-and-dynamic-polymorphism" title="Permalink to this headline">¶</a></h1>
<p>With a header only library, you can only do so much with static
polymorphism alone. There are some situations where you have to handle
dynamic polymorphism because of unavoidable runtime-based decision
making. Although you can deal with the base types that remain static,
behavior can vary greatly which derived type should be handling the
situation based on runtime values.</p>
<p>This situation comes up in the <tt class="xref py py-mod docutils literal"><span class="pre">cpp-netlib</span></tt> when we decide what
kind of connection handler to use for a given HTTP URI – whether it’s
plain HTTP or HTTPS. Although the HTTP semantics are the same for
HTTP and HTTPS the implementation of the connection handler greatly
varies on whether to use a plain TCP connection or an SSL-wrapped TCP
connection.</p>
<p>The general pattern or technique is to combine tag-based dispatch with
a strategy factory, all while not requiring any externally built
libraries. Doing it in a header-only library requires a little
creativity and additional layers of indirection that you otherwise
will not need for a library with externally built static/dynamic
libraries.</p>
<p>First we define the base type which we want to support dynamic
behavior with. There’s nothing special with the base type, except
that it supports the tag dispatch earlier defined and has a virtual
destructor. In code it looks like 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">base</span> <span class="p">{</span>
<span class="k">virtual</span> <span class="kt">void</span> <span class="n">foo</span><span class="p">()</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// make this an abstract base</span>
<span class="k">virtual</span> <span class="o">~</span><span class="n">base</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// do the base destructor thing here.</span>
<span class="p">}</span>
<span class="p">};</span>
</pre></div>
</div>
<p>We then define a set of derived types that specialize the
implementation of the <tt class="docutils literal"><span class="pre">foo</span></tt> member function. To facilitate the
dispatch of the correct type based on an input, we create a strategy
factory function:</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="n">unique_ptr</span><span class="o"><</span><span class="n">base</span><span class="o"><</span><span class="n">Tag</span><span class="o">></span> <span class="o">></span> <span class="n">strategy</span><span class="p">(</span><span class="kt">int</span> <span class="n">input</span><span class="p">,</span> <span class="n">Tag</span><span class="p">)</span> <span class="p">{</span>
<span class="n">unique_ptr</span><span class="o"><</span><span class="n">base</span><span class="o"><</span><span class="n">Tag</span><span class="o">></span> <span class="o">></span> <span class="n">ptr</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">input</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="mi">0</span>: <span class="n">ptr</span><span class="p">.</span><span class="n">reset</span><span class="p">(</span><span class="k">new</span> <span class="n">derived0</span><span class="p">());</span> <span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="mi">1</span>: <span class="n">ptr</span><span class="p">.</span><span class="n">reset</span><span class="p">(</span><span class="k">new</span> <span class="n">derived1</span><span class="p">());</span> <span class="k">break</span><span class="p">;</span>
<span class="c1">// ...</span>
<span class="nl">default:</span> <span class="n">ptr</span><span class="p">.</span><span class="n">reset</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">ptr</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">unique_ptr</span><span class="o"><</span><span class="n">base</span><span class="o"><</span><span class="n">default_</span><span class="o">></span> <span class="o">></span> <span class="n">ptr</span> <span class="o">=</span>
<span class="n">strategy</span><span class="p">(</span><span class="n">input</span><span class="p">,</span> <span class="n">default_</span><span class="p">());</span> <span class="c1">// input is a runtime value</span>
</pre></div>
</div>
<p>The strategy factory can be a standalone function, or a static member
of a factory class that is specialized by tag dispatch. This can be
done like the following:</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">strategy</span><span class="p">;</span>
<span class="k">template</span> <span class="o"><></span>
<span class="k">struct</span> <span class="n">strategy</span><span class="o"><</span><span class="n">default_</span><span class="o">></span> <span class="p">{</span>
<span class="k">static</span> <span class="n">unique_ptr</span><span class="o"><</span><span class="n">base</span><span class="o"><</span><span class="n">default_</span><span class="o">></span> <span class="o">></span> <span class="n">create</span><span class="p">(</span><span class="kt">int</span> <span class="n">input</span><span class="p">)</span> <span class="p">{</span>
<span class="n">unique_ptr</span><span class="o"><</span><span class="n">base</span><span class="o"><</span><span class="n">default_</span><span class="o">></span> <span class="o">></span> <span class="n">ptr</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">input</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="mi">0</span>: <span class="n">ptr</span><span class="p">.</span><span class="n">reset</span><span class="p">(</span><span class="k">new</span> <span class="n">derived0</span><span class="p">());</span> <span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="mi">1</span>: <span class="n">ptr</span><span class="p">.</span><span class="n">reset</span><span class="p">(</span><span class="k">new</span> <span class="n">derived1</span><span class="p">());</span> <span class="k">break</span><span class="p">;</span>
<span class="c1">//...</span>
<span class="nl">default:</span> <span class="n">ptr</span><span class="p">.</span><span class="n">reset</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">ptr</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</pre></div>
</div>
<p>This approach allows the header-only libraries to define new dynamic
types in subsequent versions of the library while keeping the
static-dynamic bridge fluid. The only down-side to this is the
possibility of derived type explosion in case there are a lot of
different strategies or specializations available – this though is
not unique to static-dynamic bridging, but is also a problem with pure
object oriented programming with dynamic polymorphism.</p>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h4>Previous topic</h4>
<p class="topless"><a href="directives.html"
title="previous chapter">Directives</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="../history.html"
title="next chapter">Project history</a></p>
<div id="searchbox" style="display: none">
<h3>Quick search</h3>
<form class="search" action="../search.html" method="get">
<input type="text" name="q" />
<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 class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../history.html" title="Project history"
>next</a></li>
<li class="right" >
<a href="directives.html" title="Directives"
>previous</a> |</li>
<li><a href="../contents.html">cpp-netlib v0.10.0</a> »</li>
<li><a href="../techniques.html" >Techniques</a> »</li>
</ul>
</div>
<div class="footer">
© Copyright 2008-2013, Glyn Matthews, Dean Michael Berris; 2013 Google, Inc..
Last updated on Jul 05, 2013.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2b1.
</div>
</body>
</html>