Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / utility / doc / html / base_from_member.html
1 <html>
2 <head>
3 <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
4 <title>Base_From_Member</title>
5 <link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
6 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7 <link rel="home" href="base_from_member.html" title="Base_From_Member">
8 </head>
9 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
10 <table cellpadding="2" width="100%"><tr>
11 <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
12 <td align="center"><a href="../../../../index.html">Home</a></td>
13 <td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
14 <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
15 <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
16 <td align="center"><a href="../../../../more/index.htm">More</a></td>
17 </tr></table>
18 <hr>
19 <div class="spirit-nav"></div>
20 <div class="article">
21 <div class="titlepage">
22 <div>
23 <div><h2 class="title">
24 <a name="base_from_member"></a>Base_From_Member</h2></div>
25 <div><div class="authorgroup"><div class="author"><h3 class="author">
26 <span class="firstname">Daryle</span> <span class="surname">Walker</span>
27 </h3></div></div></div>
28 <div><p class="copyright">Copyright &#169; 2001, 2003, 2004, 2012 Daryle
29       Walker</p></div>
30 <div><div class="legalnotice">
31 <a name="base_from_member.legal"></a><p>
32         Distributed under the Boost Software License, Version 1.0. (See accompanying
33         file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
34       </p>
35 </div></div>
36 </div>
37 <hr>
38 </div>
39 <div class="toc">
40 <p><b>Table of Contents</b></p>
41 <dl class="toc">
42 <dt><span class="section"><a href="base_from_member.html#base_from_member.rationale">Rationale</a></span></dt>
43 <dt><span class="section"><a href="base_from_member.html#base_from_member.synopsis">Synopsis</a></span></dt>
44 <dt><span class="section"><a href="base_from_member.html#base_from_member.usage">Usage</a></span></dt>
45 <dt><span class="section"><a href="base_from_member.html#base_from_member.example">Example</a></span></dt>
46 <dt><span class="section"><a href="base_from_member.html#base_from_member.acknowledgments">Acknowledgments</a></span></dt>
47 </dl>
48 </div>
49 <div class="section">
50 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
51 <a name="base_from_member.rationale"></a><a class="link" href="base_from_member.html#base_from_member.rationale" title="Rationale">Rationale</a>
52 </h2></div></div></div>
53 <p>
54       When developing a class, sometimes a base class needs to be initialized with
55       a member of the current class. As a na&#239;ve example:
56     </p>
57 <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">streambuf</span><span class="special">&gt;</span>  <span class="comment">/* for std::streambuf */</span>
58 <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">ostream</span><span class="special">&gt;</span>    <span class="comment">/* for std::ostream */</span>
59
60 <span class="keyword">class</span> <span class="identifier">fdoutbuf</span>
61   <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">streambuf</span>
62 <span class="special">{</span>
63 <span class="keyword">public</span><span class="special">:</span>
64     <span class="keyword">explicit</span> <span class="identifier">fdoutbuf</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">fd</span> <span class="special">);</span>
65     <span class="comment">//...</span>
66 <span class="special">};</span>
67
68 <span class="keyword">class</span> <span class="identifier">fdostream</span>
69   <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span>
70 <span class="special">{</span>
71 <span class="keyword">protected</span><span class="special">:</span>
72     <span class="identifier">fdoutbuf</span> <span class="identifier">buf</span><span class="special">;</span>
73 <span class="keyword">public</span><span class="special">:</span>
74     <span class="keyword">explicit</span> <span class="identifier">fdostream</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">fd</span> <span class="special">)</span>
75       <span class="special">:</span> <span class="identifier">buf</span><span class="special">(</span> <span class="identifier">fd</span> <span class="special">),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">(</span> <span class="special">&amp;</span><span class="identifier">buf</span> <span class="special">)</span> <span class="special">{}</span>
76     <span class="comment">//...</span>
77 <span class="special">};</span>
78 </pre>
79 <p>
80       This is undefined because C++'s initialization order mandates that the base
81       class is initialized before the member it uses. <a href="http://www.moocat.org" target="_top">R.
82       Samuel Klatchko</a> developed a way around this by using the initialization
83       order in his favor. Base classes are intialized in order of declaration, so
84       moving the desired member to another base class, that is initialized before
85       the desired base class, can ensure proper initialization.
86     </p>
87 <p>
88       A custom base class can be made for this idiom:
89     </p>
90 <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">streambuf</span><span class="special">&gt;</span>  <span class="comment">/* for std::streambuf */</span>
91 <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">ostream</span><span class="special">&gt;</span>    <span class="comment">/* for std::ostream */</span>
92
93 <span class="keyword">class</span> <span class="identifier">fdoutbuf</span>
94   <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">streambuf</span>
95 <span class="special">{</span>
96 <span class="keyword">public</span><span class="special">:</span>
97     <span class="keyword">explicit</span> <span class="identifier">fdoutbuf</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">fd</span> <span class="special">);</span>
98     <span class="comment">//...</span>
99 <span class="special">};</span>
100
101 <span class="keyword">struct</span> <span class="identifier">fdostream_pbase</span>
102 <span class="special">{</span>
103     <span class="identifier">fdoutbuf</span> <span class="identifier">sbuffer</span><span class="special">;</span>
104
105     <span class="keyword">explicit</span> <span class="identifier">fdostream_pbase</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">fd</span> <span class="special">)</span>
106       <span class="special">:</span> <span class="identifier">sbuffer</span><span class="special">(</span> <span class="identifier">fd</span> <span class="special">)</span> <span class="special">{}</span>
107 <span class="special">};</span>
108
109 <span class="keyword">class</span> <span class="identifier">fdostream</span>
110   <span class="special">:</span> <span class="keyword">private</span> <span class="identifier">fdostream_pbase</span>
111   <span class="special">,</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span>
112 <span class="special">{</span>
113     <span class="keyword">typedef</span> <span class="identifier">fdostream_pbase</span>  <span class="identifier">pbase_type</span><span class="special">;</span>
114     <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span>     <span class="identifier">base_type</span><span class="special">;</span>
115
116 <span class="keyword">public</span><span class="special">:</span>
117     <span class="keyword">explicit</span> <span class="identifier">fdostream</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">fd</span> <span class="special">)</span>
118       <span class="special">:</span> <span class="identifier">pbase_type</span><span class="special">(</span> <span class="identifier">fd</span> <span class="special">),</span> <span class="identifier">base_type</span><span class="special">(</span> <span class="special">&amp;</span><span class="identifier">sbuffer</span> <span class="special">)</span> <span class="special">{}</span>
119     <span class="comment">//...</span>
120 <span class="special">};</span>
121 </pre>
122 <p>
123       Other projects can use similar custom base classes. The technique is basic
124       enough to make a template, with a sample template class in this library. The
125       main template parameter is the type of the enclosed member. The template class
126       has several (explicit) constructor member templates, which implicitly type
127       the constructor arguments and pass them to the member. The template class uses
128       implicit copy construction and assignment, cancelling them if the enclosed
129       member is non-copyable.
130     </p>
131 <p>
132       Manually coding a base class may be better if the construction and/or copying
133       needs are too complex for the supplied template class, or if the compiler is
134       not advanced enough to use it.
135     </p>
136 <p>
137       Since base classes are unnamed, a class cannot have multiple (direct) base
138       classes of the same type. The supplied template class has an extra template
139       parameter, an integer, that exists solely to provide type differentiation.
140       This parameter has a default value so a single use of a particular member type
141       does not need to concern itself with the integer.
142     </p>
143 </div>
144 <div class="section">
145 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
146 <a name="base_from_member.synopsis"></a><a class="link" href="base_from_member.html#base_from_member.synopsis" title="Synopsis">Synopsis</a>
147 </h2></div></div></div>
148 <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">type_traits</span><span class="special">&gt;</span>  <span class="comment">/* exposition only */</span>
149
150 <span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_BASE_FROM_MEMBER_MAX_ARITY</span>
151 <span class="preprocessor">#define</span> <span class="identifier">BOOST_BASE_FROM_MEMBER_MAX_ARITY</span>  <span class="number">10</span>
152 <span class="preprocessor">#endif</span>
153
154 <span class="keyword">template</span> <span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">MemberType</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">UniqueID</span> <span class="special">=</span> <span class="number">0</span> <span class="special">&gt;</span>
155 <span class="keyword">class</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span>
156 <span class="special">{</span>
157 <span class="keyword">protected</span><span class="special">:</span>
158     <span class="identifier">MemberType</span>  <span class="identifier">member</span><span class="special">;</span>
159
160 <span class="preprocessor">#if</span> <span class="emphasis"><em>C++11 is in use</em></span>
161     <span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="special">...</span><span class="identifier">T</span> <span class="special">&gt;</span>
162     <span class="keyword">explicit</span> <span class="keyword">constexpr</span>   <span class="identifier">base_from_member</span><span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span> <span class="special">...</span><span class="identifier">x</span> <span class="special">)</span>
163      <span class="keyword">noexcept</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">is_nothrow_constructible</span><span class="special">&lt;</span><span class="identifier">MemberType</span><span class="special">,</span> <span class="identifier">T</span><span class="special">...&gt;::</span><span class="identifier">value</span> <span class="special">);</span>
164 <span class="preprocessor">#else</span>
165     <span class="identifier">base_from_member</span><span class="special">();</span>
166
167     <span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">T1</span> <span class="special">&gt;</span>
168     <span class="keyword">explicit</span>  <span class="identifier">base_from_member</span><span class="special">(</span> <span class="identifier">T1</span> <span class="identifier">x1</span> <span class="special">);</span>
169
170     <span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T2</span> <span class="special">&gt;</span>
171     <span class="identifier">base_from_member</span><span class="special">(</span> <span class="identifier">T1</span> <span class="identifier">x1</span><span class="special">,</span> <span class="identifier">T2</span> <span class="identifier">x2</span> <span class="special">);</span>
172
173     <span class="comment">//...</span>
174
175     <span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T2</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T3</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T4</span><span class="special">,</span>
176      <span class="keyword">typename</span> <span class="identifier">T5</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T6</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T7</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T8</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T9</span><span class="special">,</span>
177      <span class="keyword">typename</span> <span class="identifier">T10</span> <span class="special">&gt;</span>
178     <span class="identifier">base_from_member</span><span class="special">(</span> <span class="identifier">T1</span> <span class="identifier">x1</span><span class="special">,</span> <span class="identifier">T2</span> <span class="identifier">x2</span><span class="special">,</span> <span class="identifier">T3</span> <span class="identifier">x3</span><span class="special">,</span> <span class="identifier">T4</span> <span class="identifier">x4</span><span class="special">,</span> <span class="identifier">T5</span> <span class="identifier">x5</span><span class="special">,</span> <span class="identifier">T6</span> <span class="identifier">x6</span><span class="special">,</span> <span class="identifier">T7</span> <span class="identifier">x7</span><span class="special">,</span>
179      <span class="identifier">T8</span> <span class="identifier">x8</span><span class="special">,</span> <span class="identifier">T9</span> <span class="identifier">x9</span><span class="special">,</span> <span class="identifier">T10</span> <span class="identifier">x10</span> <span class="special">);</span>
180 <span class="preprocessor">#endif</span>
181 <span class="special">};</span>
182
183 <span class="keyword">template</span> <span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">MemberType</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">UniqueID</span> <span class="special">&gt;</span>
184 <span class="keyword">class</span> <span class="identifier">base_from_member</span><span class="special">&lt;</span><span class="identifier">MemberType</span><span class="special">&amp;,</span> <span class="identifier">UniqueID</span><span class="special">&gt;</span>
185 <span class="special">{</span>
186 <span class="keyword">protected</span><span class="special">:</span>
187     <span class="identifier">MemberType</span><span class="special">&amp;</span> <span class="identifier">member</span><span class="special">;</span>
188
189     <span class="keyword">explicit</span> <span class="keyword">constexpr</span> <span class="identifier">base_from_member</span><span class="special">(</span> <span class="identifier">MemberType</span><span class="special">&amp;</span> <span class="identifier">x</span> <span class="special">)</span>
190         <span class="keyword">noexcept</span><span class="special">;</span>
191 <span class="special">};</span>
192 </pre>
193 <p>
194       The class template has a first template parameter <code class="computeroutput"><span class="identifier">MemberType</span></code>
195       representing the type of the based-member. It has a last template parameter
196       <code class="computeroutput"><span class="identifier">UniqueID</span></code>, that is an <code class="computeroutput"><span class="keyword">int</span></code>, to differentiate between multiple base
197       classes that use the same based-member type. The last template parameter has
198       a default value of zero if it is omitted. The class template has a protected
199       data member called <code class="computeroutput"><span class="identifier">member</span></code> that
200       the derived class can use for later base classes (or itself).
201     </p>
202 <p>
203       If the appropriate features of C++11 are present, there will be a single constructor
204       template. It implements <span class="emphasis"><em>perfect forwarding</em></span> to the best
205       constructor call of <code class="computeroutput"><span class="identifier">member</span></code>
206       (if any). The constructor template is marked both <code class="computeroutput"><span class="keyword">constexpr</span></code>
207       and <code class="computeroutput"><span class="keyword">explicit</span></code>. The former will
208       be ignored if the corresponding inner constructor call (of <code class="computeroutput"><span class="identifier">member</span></code>)
209       does not have the marker. The latter binds the other way; always taking effect,
210       even when the inner constructor call does not have the marker. The constructor
211       template propagates the <code class="computeroutput"><span class="keyword">noexcept</span></code>
212       status of the inner constructor call. (The constructor template has a trailing
213       parameter with a default value that disables the template when its signature
214       is too close to the signatures of the automatically-defined non-template copy-
215       and/or move-constructors of <code class="computeroutput"><span class="identifier">base_from_member</span></code>.)
216     </p>
217 <p>
218       On earlier-standard compilers, there is a default constructor and several constructor
219       member templates. These constructor templates can take as many arguments (currently
220       up to ten) as possible and pass them to a constructor of the data member.
221     </p>
222 <p>
223       A specialization for member references offers a single constructor taking a
224       <code class="computeroutput"><span class="identifier">MemberType</span><span class="special">&amp;</span></code>,
225       which is the only way to initialize a reference.
226     </p>
227 <p>
228       Since C++ does not allow any way to explicitly state the template parameters
229       of a templated constructor, make sure that the arguments are already close
230       as possible to the actual type used in the data member's desired constructor.
231       Explicit conversions may be necessary.
232     </p>
233 <p>
234       The <code class="computeroutput"><span class="identifier">BOOST_BASE_FROM_MEMBER_MAX_ARITY</span></code>
235       macro constant specifies the maximum argument length for the constructor templates.
236       The constant may be overridden if more (or less) argument configurations are
237       needed. The constant may be read for code that is expandable like the class
238       template and needs to maintain the same maximum size. (Example code would be
239       a class that uses this class template as a base class for a member with a flexible
240       set of constructors.) This constant is ignored when C++11 features are present.
241     </p>
242 </div>
243 <div class="section">
244 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
245 <a name="base_from_member.usage"></a><a class="link" href="base_from_member.html#base_from_member.usage" title="Usage">Usage</a>
246 </h2></div></div></div>
247 <p>
248       With the starting example, the <code class="computeroutput"><span class="identifier">fdoutbuf</span></code>
249       sub-object needs to be encapsulated in a base class that is inheirited before
250       <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span></code>.
251     </p>
252 <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">base_from_member</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
253
254 <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">streambuf</span><span class="special">&gt;</span>  <span class="comment">// for std::streambuf</span>
255 <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">ostream</span><span class="special">&gt;</span>    <span class="comment">// for std::ostream</span>
256
257 <span class="keyword">class</span> <span class="identifier">fdoutbuf</span>
258   <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">streambuf</span>
259 <span class="special">{</span>
260 <span class="keyword">public</span><span class="special">:</span>
261     <span class="keyword">explicit</span> <span class="identifier">fdoutbuf</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">fd</span> <span class="special">);</span>
262     <span class="comment">//...</span>
263 <span class="special">};</span>
264
265 <span class="keyword">class</span> <span class="identifier">fdostream</span>
266   <span class="special">:</span> <span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span><span class="identifier">fdoutbuf</span><span class="special">&gt;</span>
267   <span class="special">,</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span>
268 <span class="special">{</span>
269     <span class="comment">// Helper typedef's</span>
270     <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span><span class="identifier">fdoutbuf</span><span class="special">&gt;</span>  <span class="identifier">pbase_type</span><span class="special">;</span>
271     <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span>                        <span class="identifier">base_type</span><span class="special">;</span>
272
273 <span class="keyword">public</span><span class="special">:</span>
274     <span class="keyword">explicit</span> <span class="identifier">fdostream</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">fd</span> <span class="special">)</span>
275       <span class="special">:</span> <span class="identifier">pbase_type</span><span class="special">(</span> <span class="identifier">fd</span> <span class="special">),</span> <span class="identifier">base_type</span><span class="special">(</span> <span class="special">&amp;</span><span class="identifier">member</span> <span class="special">){}</span>
276     <span class="comment">//...</span>
277 <span class="special">};</span>
278 </pre>
279 <p>
280       The base-from-member idiom is an implementation detail, so it should not be
281       visible to the clients (or any derived classes) of <code class="computeroutput"><span class="identifier">fdostream</span></code>.
282       Due to the initialization order, the <code class="computeroutput"><span class="identifier">fdoutbuf</span></code>
283       sub-object will get initialized before the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span></code>
284       sub-object does, making the former sub-object safe to use in the latter sub-object's
285       construction. Since the <code class="computeroutput"><span class="identifier">fdoutbuf</span></code>
286       sub-object of the final type is the only sub-object with the name <code class="computeroutput"><span class="identifier">member</span></code> that name can be used unqualified
287       within the final class.
288     </p>
289 </div>
290 <div class="section">
291 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
292 <a name="base_from_member.example"></a><a class="link" href="base_from_member.html#base_from_member.example" title="Example">Example</a>
293 </h2></div></div></div>
294 <p>
295       The base-from-member class templates should commonly involve only one base-from-member
296       sub-object, usually for attaching a stream-buffer to an I/O stream. The next
297       example demonstrates how to use multiple base-from-member sub-objects and the
298       resulting qualification issues.
299     </p>
300 <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">base_from_member</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
301
302 <span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cstddef</span><span class="special">&gt;</span>  <span class="comment">/* for NULL */</span>
303
304 <span class="keyword">struct</span> <span class="identifier">an_int</span>
305 <span class="special">{</span>
306     <span class="keyword">int</span>  <span class="identifier">y</span><span class="special">;</span>
307
308     <span class="identifier">an_int</span><span class="special">(</span> <span class="keyword">float</span> <span class="identifier">yf</span> <span class="special">);</span>
309 <span class="special">};</span>
310
311 <span class="keyword">class</span> <span class="identifier">switcher</span>
312 <span class="special">{</span>
313 <span class="keyword">public</span><span class="special">:</span>
314     <span class="identifier">switcher</span><span class="special">();</span>
315     <span class="identifier">switcher</span><span class="special">(</span> <span class="keyword">double</span><span class="special">,</span> <span class="keyword">int</span> <span class="special">*</span> <span class="special">);</span>
316     <span class="comment">//...</span>
317 <span class="special">};</span>
318
319 <span class="keyword">class</span> <span class="identifier">flow_regulator</span>
320 <span class="special">{</span>
321 <span class="keyword">public</span><span class="special">:</span>
322     <span class="identifier">flow_regulator</span><span class="special">(</span> <span class="identifier">switcher</span> <span class="special">&amp;,</span> <span class="identifier">switcher</span> <span class="special">&amp;</span> <span class="special">);</span>
323     <span class="comment">//...</span>
324 <span class="special">};</span>
325
326 <span class="keyword">template</span> <span class="special">&lt;</span> <span class="keyword">unsigned</span> <span class="identifier">Size</span> <span class="special">&gt;</span>
327 <span class="keyword">class</span> <span class="identifier">fan</span>
328 <span class="special">{</span>
329 <span class="keyword">public</span><span class="special">:</span>
330     <span class="keyword">explicit</span> <span class="identifier">fan</span><span class="special">(</span> <span class="identifier">switcher</span> <span class="special">);</span>
331     <span class="comment">//...</span>
332 <span class="special">};</span>
333
334 <span class="keyword">class</span> <span class="identifier">system</span>
335   <span class="special">:</span> <span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span><span class="identifier">an_int</span><span class="special">&gt;</span>
336   <span class="special">,</span> <span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span><span class="identifier">switcher</span><span class="special">&gt;</span>
337   <span class="special">,</span> <span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span><span class="identifier">switcher</span><span class="special">,</span> <span class="number">1</span><span class="special">&gt;</span>
338   <span class="special">,</span> <span class="keyword">private</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span><span class="identifier">switcher</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span>
339   <span class="special">,</span> <span class="keyword">protected</span> <span class="identifier">flow_regulator</span>
340   <span class="special">,</span> <span class="keyword">public</span> <span class="identifier">fan</span><span class="special">&lt;</span><span class="number">6</span><span class="special">&gt;</span>
341 <span class="special">{</span>
342     <span class="comment">// Helper typedef's</span>
343     <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span><span class="identifier">an_int</span><span class="special">&gt;</span>       <span class="identifier">pbase0_type</span><span class="special">;</span>
344     <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span><span class="identifier">switcher</span><span class="special">&gt;</span>     <span class="identifier">pbase1_type</span><span class="special">;</span>
345     <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span><span class="identifier">switcher</span><span class="special">,</span> <span class="number">1</span><span class="special">&gt;</span>  <span class="identifier">pbase2_type</span><span class="special">;</span>
346     <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span><span class="identifier">switcher</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;</span>  <span class="identifier">pbase3_type</span><span class="special">;</span>
347
348     <span class="keyword">typedef</span> <span class="identifier">flow_regulator</span>  <span class="identifier">base1_type</span><span class="special">;</span>
349     <span class="keyword">typedef</span> <span class="identifier">fan</span><span class="special">&lt;</span><span class="number">6</span><span class="special">&gt;</span>          <span class="identifier">base2_type</span><span class="special">;</span>
350
351 <span class="keyword">public</span><span class="special">:</span>
352     <span class="identifier">system</span><span class="special">(</span> <span class="keyword">double</span> <span class="identifier">x</span> <span class="special">);</span>
353     <span class="comment">//...</span>
354 <span class="special">};</span>
355
356 <span class="identifier">system</span><span class="special">::</span><span class="identifier">system</span><span class="special">(</span> <span class="keyword">double</span> <span class="identifier">x</span> <span class="special">)</span>
357   <span class="special">:</span> <span class="identifier">pbase0_type</span><span class="special">(</span> <span class="number">0.2</span> <span class="special">)</span>
358   <span class="special">,</span> <span class="identifier">pbase1_type</span><span class="special">()</span>
359   <span class="special">,</span> <span class="identifier">pbase2_type</span><span class="special">(</span> <span class="special">-</span><span class="number">16</span><span class="special">,</span> <span class="special">&amp;</span><span class="keyword">this</span><span class="special">-&gt;</span><span class="identifier">pbase0_type</span><span class="special">::</span><span class="identifier">member</span><span class="special">.</span><span class="identifier">y</span> <span class="special">)</span>
360   <span class="special">,</span> <span class="identifier">pbase3_type</span><span class="special">(</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="keyword">int</span> <span class="special">*&gt;(</span><span class="identifier">NULL</span><span class="special">)</span> <span class="special">)</span>
361   <span class="special">,</span> <span class="identifier">base1_type</span><span class="special">(</span> <span class="identifier">pbase3_type</span><span class="special">::</span><span class="identifier">member</span><span class="special">,</span> <span class="identifier">pbase1_type</span><span class="special">::</span><span class="identifier">member</span> <span class="special">)</span>
362   <span class="special">,</span> <span class="identifier">base2_type</span><span class="special">(</span> <span class="identifier">pbase2_type</span><span class="special">::</span><span class="identifier">member</span> <span class="special">)</span>
363 <span class="special">{</span>
364     <span class="comment">//...</span>
365 <span class="special">}</span>
366 </pre>
367 <p>
368       The final class has multiple sub-objects with the name <code class="computeroutput"><span class="identifier">member</span></code>,
369       so any use of that name needs qualification by a name of the appropriate base
370       type. (Using <code class="computeroutput"><span class="keyword">typedef</span></code>s ease mentioning
371       the base types.) However, the fix introduces a new problem when a pointer is
372       needed. Using the address operator with a sub-object qualified with its class's
373       name results in a pointer-to-member (here, having a type of <code class="computeroutput"><span class="identifier">an_int</span>
374       <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span>
375       <span class="identifier">an_int</span><span class="special">,</span>
376       <span class="number">0</span><span class="special">&gt;</span> <span class="special">::</span> <span class="special">*</span></code>) instead
377       of a pointer to the member (having a type of <code class="computeroutput"><span class="identifier">an_int</span>
378       <span class="special">*</span></code>). The new problem is fixed by qualifying
379       the sub-object with <code class="computeroutput"><span class="keyword">this</span><span class="special">-&gt;</span></code>
380       and is needed just for pointers, and not for references or values.
381     </p>
382 <p>
383       There are some argument conversions in the initialization. The constructor
384       argument for <code class="computeroutput"><span class="identifier">pbase0_type</span></code> is
385       converted from <code class="computeroutput"><span class="keyword">double</span></code> to <code class="computeroutput"><span class="keyword">float</span></code>. The first constructor argument for <code class="computeroutput"><span class="identifier">pbase2_type</span></code> is converted from <code class="computeroutput"><span class="keyword">int</span></code> to <code class="computeroutput"><span class="keyword">double</span></code>.
386       The second constructor argument for <code class="computeroutput"><span class="identifier">pbase3_type</span></code>
387       is a special case of necessary conversion; all forms of the null-pointer literal
388       in C++ (except <code class="computeroutput"><span class="keyword">nullptr</span></code> from C++11)
389       also look like compile-time integral expressions, so C++ always interprets
390       such code as an integer when it has overloads that can take either an integer
391       or a pointer. The last conversion is necessary for the compiler to call a constructor
392       form with the exact pointer type used in <code class="computeroutput"><span class="identifier">switcher</span></code>'s
393       constructor. (If C++11's <code class="computeroutput"><span class="keyword">nullptr</span></code>
394       is used, it still needs a conversion if multiple pointer types can be accepted
395       in a constructor call but <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">nullptr_t</span></code>
396       cannot.)
397     </p>
398 </div>
399 <div class="section">
400 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
401 <a name="base_from_member.acknowledgments"></a><a class="link" href="base_from_member.html#base_from_member.acknowledgments" title="Acknowledgments">Acknowledgments</a>
402 </h2></div></div></div>
403 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
404 <li class="listitem">
405           <a href="http://www.boost.org/people/ed_brey.htm" target="_top">Ed Brey</a> suggested
406           some interface changes.
407         </li>
408 <li class="listitem">
409           <a href="http://www.moocat.org" target="_top">R. Samuel Klatchko</a> (<a href="mailto:rsk%40moocat.org" target="_top">rsk@moocat.org</a>,
410           <a href="mailto:rsk%40brightmail.com" target="_top">rsk@brightmail.com</a>) invented
411           the idiom of how to use a class member for initializing a base class.
412         </li>
413 <li class="listitem">
414           <a href="http://www.boost.org/people/dietmar_kuehl.htm" target="_top">Dietmar Kuehl</a>
415           popularized the base-from-member idiom in his <a href="http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/" target="_top">IOStream
416           example classes</a>.
417         </li>
418 <li class="listitem">
419           Jonathan Turkanis supplied an implementation of generating the constructor
420           templates that can be controlled and automated with macros. The implementation
421           uses the <a href="../../../preprocessor/index.html" target="_top">Preprocessor library</a>.
422         </li>
423 <li class="listitem">
424           <a href="http://www.boost.org/people/daryle_walker.html%22%3eDaryle" target="_top">Walker</a>
425           started the library. Contributed the test file <a href="../../test/base_from_member_test.cpp" target="_top">base_from_member_test.cpp</a>.
426         </li>
427 </ul></div>
428 </div>
429 </div>
430 <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
431 <td align="left"><p><small>Last revised: December 10, 2019 at 00:21:47 GMT</small></p></td>
432 <td align="right"><div class="copyright-footer"></div></td>
433 </tr></table>
434 <hr>
435 <div class="spirit-nav"></div>
436 </body>
437 </html>