base_from_member.html 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  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. <span class="keyword">class</span> <span class="identifier">fdoutbuf</span>
  60. <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">streambuf</span>
  61. <span class="special">{</span>
  62. <span class="keyword">public</span><span class="special">:</span>
  63. <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>
  64. <span class="comment">//...</span>
  65. <span class="special">};</span>
  66. <span class="keyword">class</span> <span class="identifier">fdostream</span>
  67. <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span>
  68. <span class="special">{</span>
  69. <span class="keyword">protected</span><span class="special">:</span>
  70. <span class="identifier">fdoutbuf</span> <span class="identifier">buf</span><span class="special">;</span>
  71. <span class="keyword">public</span><span class="special">:</span>
  72. <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>
  73. <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>
  74. <span class="comment">//...</span>
  75. <span class="special">};</span>
  76. </pre>
  77. <p>
  78. This is undefined because C++'s initialization order mandates that the base
  79. class is initialized before the member it uses. <a href="http://www.moocat.org" target="_top">R.
  80. Samuel Klatchko</a> developed a way around this by using the initialization
  81. order in his favor. Base classes are intialized in order of declaration, so
  82. moving the desired member to another base class, that is initialized before
  83. the desired base class, can ensure proper initialization.
  84. </p>
  85. <p>
  86. A custom base class can be made for this idiom:
  87. </p>
  88. <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>
  89. <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>
  90. <span class="keyword">class</span> <span class="identifier">fdoutbuf</span>
  91. <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">streambuf</span>
  92. <span class="special">{</span>
  93. <span class="keyword">public</span><span class="special">:</span>
  94. <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>
  95. <span class="comment">//...</span>
  96. <span class="special">};</span>
  97. <span class="keyword">struct</span> <span class="identifier">fdostream_pbase</span>
  98. <span class="special">{</span>
  99. <span class="identifier">fdoutbuf</span> <span class="identifier">sbuffer</span><span class="special">;</span>
  100. <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>
  101. <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>
  102. <span class="special">};</span>
  103. <span class="keyword">class</span> <span class="identifier">fdostream</span>
  104. <span class="special">:</span> <span class="keyword">private</span> <span class="identifier">fdostream_pbase</span>
  105. <span class="special">,</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span>
  106. <span class="special">{</span>
  107. <span class="keyword">typedef</span> <span class="identifier">fdostream_pbase</span> <span class="identifier">pbase_type</span><span class="special">;</span>
  108. <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>
  109. <span class="keyword">public</span><span class="special">:</span>
  110. <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>
  111. <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>
  112. <span class="comment">//...</span>
  113. <span class="special">};</span>
  114. </pre>
  115. <p>
  116. Other projects can use similar custom base classes. The technique is basic
  117. enough to make a template, with a sample template class in this library. The
  118. main template parameter is the type of the enclosed member. The template class
  119. has several (explicit) constructor member templates, which implicitly type
  120. the constructor arguments and pass them to the member. The template class uses
  121. implicit copy construction and assignment, cancelling them if the enclosed
  122. member is non-copyable.
  123. </p>
  124. <p>
  125. Manually coding a base class may be better if the construction and/or copying
  126. needs are too complex for the supplied template class, or if the compiler is
  127. not advanced enough to use it.
  128. </p>
  129. <p>
  130. Since base classes are unnamed, a class cannot have multiple (direct) base
  131. classes of the same type. The supplied template class has an extra template
  132. parameter, an integer, that exists solely to provide type differentiation.
  133. This parameter has a default value so a single use of a particular member type
  134. does not need to concern itself with the integer.
  135. </p>
  136. </div>
  137. <div class="section">
  138. <div class="titlepage"><div><div><h2 class="title" style="clear: both">
  139. <a name="base_from_member.synopsis"></a><a class="link" href="base_from_member.html#base_from_member.synopsis" title="Synopsis">Synopsis</a>
  140. </h2></div></div></div>
  141. <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>
  142. <span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_BASE_FROM_MEMBER_MAX_ARITY</span>
  143. <span class="preprocessor">#define</span> <span class="identifier">BOOST_BASE_FROM_MEMBER_MAX_ARITY</span> <span class="number">10</span>
  144. <span class="preprocessor">#endif</span>
  145. <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>
  146. <span class="keyword">class</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span>
  147. <span class="special">{</span>
  148. <span class="keyword">protected</span><span class="special">:</span>
  149. <span class="identifier">MemberType</span> <span class="identifier">member</span><span class="special">;</span>
  150. <span class="preprocessor">#if</span> <span class="emphasis"><em>C++11 is in use</em></span>
  151. <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>
  152. <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>
  153. <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>
  154. <span class="preprocessor">#else</span>
  155. <span class="identifier">base_from_member</span><span class="special">();</span>
  156. <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>
  157. <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>
  158. <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>
  159. <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>
  160. <span class="comment">//...</span>
  161. <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>
  162. <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>
  163. <span class="keyword">typename</span> <span class="identifier">T10</span> <span class="special">&gt;</span>
  164. <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>
  165. <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>
  166. <span class="preprocessor">#endif</span>
  167. <span class="special">};</span>
  168. <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>
  169. <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>
  170. <span class="special">{</span>
  171. <span class="keyword">protected</span><span class="special">:</span>
  172. <span class="identifier">MemberType</span><span class="special">&amp;</span> <span class="identifier">member</span><span class="special">;</span>
  173. <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>
  174. <span class="keyword">noexcept</span><span class="special">;</span>
  175. <span class="special">};</span>
  176. </pre>
  177. <p>
  178. The class template has a first template parameter <code class="computeroutput"><span class="identifier">MemberType</span></code>
  179. representing the type of the based-member. It has a last template parameter
  180. <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
  181. classes that use the same based-member type. The last template parameter has
  182. a default value of zero if it is omitted. The class template has a protected
  183. data member called <code class="computeroutput"><span class="identifier">member</span></code> that
  184. the derived class can use for later base classes (or itself).
  185. </p>
  186. <p>
  187. If the appropriate features of C++11 are present, there will be a single constructor
  188. template. It implements <span class="emphasis"><em>perfect forwarding</em></span> to the best
  189. constructor call of <code class="computeroutput"><span class="identifier">member</span></code>
  190. (if any). The constructor template is marked both <code class="computeroutput"><span class="keyword">constexpr</span></code>
  191. and <code class="computeroutput"><span class="keyword">explicit</span></code>. The former will
  192. be ignored if the corresponding inner constructor call (of <code class="computeroutput"><span class="identifier">member</span></code>)
  193. does not have the marker. The latter binds the other way; always taking effect,
  194. even when the inner constructor call does not have the marker. The constructor
  195. template propagates the <code class="computeroutput"><span class="keyword">noexcept</span></code>
  196. status of the inner constructor call. (The constructor template has a trailing
  197. parameter with a default value that disables the template when its signature
  198. is too close to the signatures of the automatically-defined non-template copy-
  199. and/or move-constructors of <code class="computeroutput"><span class="identifier">base_from_member</span></code>.)
  200. </p>
  201. <p>
  202. On earlier-standard compilers, there is a default constructor and several constructor
  203. member templates. These constructor templates can take as many arguments (currently
  204. up to ten) as possible and pass them to a constructor of the data member.
  205. </p>
  206. <p>
  207. A specialization for member references offers a single constructor taking a
  208. <code class="computeroutput"><span class="identifier">MemberType</span><span class="special">&amp;</span></code>,
  209. which is the only way to initialize a reference.
  210. </p>
  211. <p>
  212. Since C++ does not allow any way to explicitly state the template parameters
  213. of a templated constructor, make sure that the arguments are already close
  214. as possible to the actual type used in the data member's desired constructor.
  215. Explicit conversions may be necessary.
  216. </p>
  217. <p>
  218. The <code class="computeroutput"><span class="identifier">BOOST_BASE_FROM_MEMBER_MAX_ARITY</span></code>
  219. macro constant specifies the maximum argument length for the constructor templates.
  220. The constant may be overridden if more (or less) argument configurations are
  221. needed. The constant may be read for code that is expandable like the class
  222. template and needs to maintain the same maximum size. (Example code would be
  223. a class that uses this class template as a base class for a member with a flexible
  224. set of constructors.) This constant is ignored when C++11 features are present.
  225. </p>
  226. </div>
  227. <div class="section">
  228. <div class="titlepage"><div><div><h2 class="title" style="clear: both">
  229. <a name="base_from_member.usage"></a><a class="link" href="base_from_member.html#base_from_member.usage" title="Usage">Usage</a>
  230. </h2></div></div></div>
  231. <p>
  232. With the starting example, the <code class="computeroutput"><span class="identifier">fdoutbuf</span></code>
  233. sub-object needs to be encapsulated in a base class that is inheirited before
  234. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span></code>.
  235. </p>
  236. <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>
  237. <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>
  238. <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>
  239. <span class="keyword">class</span> <span class="identifier">fdoutbuf</span>
  240. <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">streambuf</span>
  241. <span class="special">{</span>
  242. <span class="keyword">public</span><span class="special">:</span>
  243. <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>
  244. <span class="comment">//...</span>
  245. <span class="special">};</span>
  246. <span class="keyword">class</span> <span class="identifier">fdostream</span>
  247. <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>
  248. <span class="special">,</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span>
  249. <span class="special">{</span>
  250. <span class="comment">// Helper typedef's</span>
  251. <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>
  252. <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>
  253. <span class="keyword">public</span><span class="special">:</span>
  254. <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>
  255. <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>
  256. <span class="comment">//...</span>
  257. <span class="special">};</span>
  258. </pre>
  259. <p>
  260. The base-from-member idiom is an implementation detail, so it should not be
  261. visible to the clients (or any derived classes) of <code class="computeroutput"><span class="identifier">fdostream</span></code>.
  262. Due to the initialization order, the <code class="computeroutput"><span class="identifier">fdoutbuf</span></code>
  263. 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>
  264. sub-object does, making the former sub-object safe to use in the latter sub-object's
  265. construction. Since the <code class="computeroutput"><span class="identifier">fdoutbuf</span></code>
  266. 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
  267. within the final class.
  268. </p>
  269. </div>
  270. <div class="section">
  271. <div class="titlepage"><div><div><h2 class="title" style="clear: both">
  272. <a name="base_from_member.example"></a><a class="link" href="base_from_member.html#base_from_member.example" title="Example">Example</a>
  273. </h2></div></div></div>
  274. <p>
  275. The base-from-member class templates should commonly involve only one base-from-member
  276. sub-object, usually for attaching a stream-buffer to an I/O stream. The next
  277. example demonstrates how to use multiple base-from-member sub-objects and the
  278. resulting qualification issues.
  279. </p>
  280. <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>
  281. <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>
  282. <span class="keyword">struct</span> <span class="identifier">an_int</span>
  283. <span class="special">{</span>
  284. <span class="keyword">int</span> <span class="identifier">y</span><span class="special">;</span>
  285. <span class="identifier">an_int</span><span class="special">(</span> <span class="keyword">float</span> <span class="identifier">yf</span> <span class="special">);</span>
  286. <span class="special">};</span>
  287. <span class="keyword">class</span> <span class="identifier">switcher</span>
  288. <span class="special">{</span>
  289. <span class="keyword">public</span><span class="special">:</span>
  290. <span class="identifier">switcher</span><span class="special">();</span>
  291. <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>
  292. <span class="comment">//...</span>
  293. <span class="special">};</span>
  294. <span class="keyword">class</span> <span class="identifier">flow_regulator</span>
  295. <span class="special">{</span>
  296. <span class="keyword">public</span><span class="special">:</span>
  297. <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>
  298. <span class="comment">//...</span>
  299. <span class="special">};</span>
  300. <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>
  301. <span class="keyword">class</span> <span class="identifier">fan</span>
  302. <span class="special">{</span>
  303. <span class="keyword">public</span><span class="special">:</span>
  304. <span class="keyword">explicit</span> <span class="identifier">fan</span><span class="special">(</span> <span class="identifier">switcher</span> <span class="special">);</span>
  305. <span class="comment">//...</span>
  306. <span class="special">};</span>
  307. <span class="keyword">class</span> <span class="identifier">system</span>
  308. <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>
  309. <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>
  310. <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>
  311. <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>
  312. <span class="special">,</span> <span class="keyword">protected</span> <span class="identifier">flow_regulator</span>
  313. <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>
  314. <span class="special">{</span>
  315. <span class="comment">// Helper typedef's</span>
  316. <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>
  317. <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>
  318. <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>
  319. <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>
  320. <span class="keyword">typedef</span> <span class="identifier">flow_regulator</span> <span class="identifier">base1_type</span><span class="special">;</span>
  321. <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>
  322. <span class="keyword">public</span><span class="special">:</span>
  323. <span class="identifier">system</span><span class="special">(</span> <span class="keyword">double</span> <span class="identifier">x</span> <span class="special">);</span>
  324. <span class="comment">//...</span>
  325. <span class="special">};</span>
  326. <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>
  327. <span class="special">:</span> <span class="identifier">pbase0_type</span><span class="special">(</span> <span class="number">0.2</span> <span class="special">)</span>
  328. <span class="special">,</span> <span class="identifier">pbase1_type</span><span class="special">()</span>
  329. <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>
  330. <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>
  331. <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>
  332. <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>
  333. <span class="special">{</span>
  334. <span class="comment">//...</span>
  335. <span class="special">}</span>
  336. </pre>
  337. <p>
  338. The final class has multiple sub-objects with the name <code class="computeroutput"><span class="identifier">member</span></code>,
  339. so any use of that name needs qualification by a name of the appropriate base
  340. type. (Using <code class="computeroutput"><span class="keyword">typedef</span></code>s ease mentioning
  341. the base types.) However, the fix introduces a new problem when a pointer is
  342. needed. Using the address operator with a sub-object qualified with its class's
  343. name results in a pointer-to-member (here, having a type of <code class="computeroutput"><span class="identifier">an_int</span>
  344. <span class="identifier">boost</span><span class="special">::</span><span class="identifier">base_from_member</span><span class="special">&lt;</span>
  345. <span class="identifier">an_int</span><span class="special">,</span>
  346. <span class="number">0</span><span class="special">&gt;</span> <span class="special">::</span> <span class="special">*</span></code>) instead
  347. of a pointer to the member (having a type of <code class="computeroutput"><span class="identifier">an_int</span>
  348. <span class="special">*</span></code>). The new problem is fixed by qualifying
  349. the sub-object with <code class="computeroutput"><span class="keyword">this</span><span class="special">-&gt;</span></code>
  350. and is needed just for pointers, and not for references or values.
  351. </p>
  352. <p>
  353. There are some argument conversions in the initialization. The constructor
  354. argument for <code class="computeroutput"><span class="identifier">pbase0_type</span></code> is
  355. 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>.
  356. The second constructor argument for <code class="computeroutput"><span class="identifier">pbase3_type</span></code>
  357. is a special case of necessary conversion; all forms of the null-pointer literal
  358. in C++ (except <code class="computeroutput"><span class="keyword">nullptr</span></code> from C++11)
  359. also look like compile-time integral expressions, so C++ always interprets
  360. such code as an integer when it has overloads that can take either an integer
  361. or a pointer. The last conversion is necessary for the compiler to call a constructor
  362. form with the exact pointer type used in <code class="computeroutput"><span class="identifier">switcher</span></code>'s
  363. constructor. (If C++11's <code class="computeroutput"><span class="keyword">nullptr</span></code>
  364. is used, it still needs a conversion if multiple pointer types can be accepted
  365. in a constructor call but <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">nullptr_t</span></code>
  366. cannot.)
  367. </p>
  368. </div>
  369. <div class="section">
  370. <div class="titlepage"><div><div><h2 class="title" style="clear: both">
  371. <a name="base_from_member.acknowledgments"></a><a class="link" href="base_from_member.html#base_from_member.acknowledgments" title="Acknowledgments">Acknowledgments</a>
  372. </h2></div></div></div>
  373. <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  374. <li class="listitem">
  375. <a href="http://www.boost.org/people/ed_brey.htm" target="_top">Ed Brey</a> suggested
  376. some interface changes.
  377. </li>
  378. <li class="listitem">
  379. <a href="http://www.moocat.org" target="_top">R. Samuel Klatchko</a> (<a href="mailto:rsk%40moocat.org" target="_top">rsk@moocat.org</a>,
  380. <a href="mailto:rsk%40brightmail.com" target="_top">rsk@brightmail.com</a>) invented
  381. the idiom of how to use a class member for initializing a base class.
  382. </li>
  383. <li class="listitem">
  384. <a href="http://www.boost.org/people/dietmar_kuehl.htm" target="_top">Dietmar Kuehl</a>
  385. popularized the base-from-member idiom in his <a href="http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/" target="_top">IOStream
  386. example classes</a>.
  387. </li>
  388. <li class="listitem">
  389. Jonathan Turkanis supplied an implementation of generating the constructor
  390. templates that can be controlled and automated with macros. The implementation
  391. uses the <a href="../../../preprocessor/index.html" target="_top">Preprocessor library</a>.
  392. </li>
  393. <li class="listitem">
  394. <a href="http://www.boost.org/people/daryle_walker.html%22%3eDaryle" target="_top">Walker</a>
  395. started the library. Contributed the test file <a href="../../test/base_from_member_test.cpp" target="_top">base_from_member_test.cpp</a>.
  396. </li>
  397. </ul></div>
  398. </div>
  399. </div>
  400. <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
  401. <td align="left"><p><small>Last revised: December 10, 2019 at 00:21:47 GMT</small></p></td>
  402. <td align="right"><div class="copyright-footer"></div></td>
  403. </tr></table>
  404. <hr>
  405. <div class="spirit-nav"></div>
  406. </body>
  407. </html>