1<html> 2<head> 3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 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 © 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ïve example: 56 </p> 57<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">streambuf</span><span class="special">></span> <span class="comment">/* for std::streambuf */</span> 58<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">ostream</span><span class="special">></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">&</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"><</span><span class="identifier">streambuf</span><span class="special">></span> <span class="comment">/* for std::streambuf */</span> 91<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">ostream</span><span class="special">></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">&</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"><</span><span class="identifier">type_traits</span><span class="special">></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"><</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">></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"><</span> <span class="keyword">typename</span> <span class="special">...</span><span class="identifier">T</span> <span class="special">></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">&&</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"><</span><span class="identifier">MemberType</span><span class="special">,</span> <span class="identifier">T</span><span class="special">...>::</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"><</span> <span class="keyword">typename</span> <span class="identifier">T1</span> <span class="special">></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"><</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> 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"><</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">></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"><</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> 184<span class="keyword">class</span> <span class="identifier">base_from_member</span><span class="special"><</span><span class="identifier">MemberType</span><span class="special">&,</span> <span class="identifier">UniqueID</span><span class="special">></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">&</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">&</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">&</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"><</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">></span> 253 254<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">streambuf</span><span class="special">></span> <span class="comment">// for std::streambuf</span> 255<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">ostream</span><span class="special">></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"><</span><span class="identifier">fdoutbuf</span><span class="special">></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"><</span><span class="identifier">fdoutbuf</span><span class="special">></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">&</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"><</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">></span> 301 302<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cstddef</span><span class="special">></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">&,</span> <span class="identifier">switcher</span> <span class="special">&</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"><</span> <span class="keyword">unsigned</span> <span class="identifier">Size</span> <span class="special">></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"><</span><span class="identifier">an_int</span><span class="special">></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"><</span><span class="identifier">switcher</span><span class="special">></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"><</span><span class="identifier">switcher</span><span class="special">,</span> <span class="number">1</span><span class="special">></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"><</span><span class="identifier">switcher</span><span class="special">,</span> <span class="number">2</span><span class="special">></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"><</span><span class="number">6</span><span class="special">></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"><</span><span class="identifier">an_int</span><span class="special">></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"><</span><span class="identifier">switcher</span><span class="special">></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"><</span><span class="identifier">switcher</span><span class="special">,</span> <span class="number">1</span><span class="special">></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"><</span><span class="identifier">switcher</span><span class="special">,</span> <span class="number">2</span><span class="special">></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"><</span><span class="number">6</span><span class="special">></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">&</span><span class="keyword">this</span><span class="special">-></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"><</span><span class="keyword">int</span> <span class="special">*>(</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"><</span> 375 <span class="identifier">an_int</span><span class="special">,</span> 376 <span class="number">0</span><span class="special">></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">-></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: August 11, 2020 at 14:59:06 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> 438