| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> |
| <html> |
| <head> |
| <title>Boost: Base-from-Member Idiom Documentation</title> |
| </head> |
| |
| <body bgcolor="white" link="blue" text="black" vlink="purple" alink="red"> |
| <h1><img src="../../boost.png" alt="C++ Boost" align="middle" |
| width="277" height="86">Base-from-Member Idiom</h1> |
| |
| <p>The class template <code>boost::base_from_member</code> provides |
| a workaround for a class that needs to initialize a base class with a |
| member. The class template is in <cite><a |
| href="../../boost/utility/base_from_member.hpp">boost/utility/base_from_member.hpp</a></cite> |
| which is included in <i><a href="../../boost/utility.hpp">boost/utility.hpp</a></i>.</p> |
| |
| <p>There is test/example code in <cite><a |
| href="base_from_member_test.cpp">base_from_member_test.cpp</a></cite>.</p> |
| |
| <h2><a name="contents">Contents</a></h2> |
| |
| <ul> |
| <li><a href="#contents">Contents</a></li> |
| <li><a href="#rationale">Rationale</a></li> |
| <li><a href="#synopsis">Synopsis</a></li> |
| <li><a href="#usage">Usage</a></li> |
| <li><a href="#example">Example</a></li> |
| <li><a href="#credits">Credits</a> |
| <ul> |
| <li><a href="#contributors">Contributors</a></li> |
| </ul></li> |
| </ul> |
| |
| <h2><a name="rationale">Rationale</a></h2> |
| |
| <p>When developing a class, sometimes a base class needs to be |
| initialized with a member of the current class. As a naïve |
| example:</p> |
| |
| <blockquote><pre> |
| #include <streambuf> <i>// for std::streambuf</i> |
| #include <ostream> <i>// for std::ostream</i> |
| |
| class fdoutbuf |
| : public std::streambuf |
| { |
| public: |
| explicit fdoutbuf( int fd ); |
| //... |
| }; |
| |
| class fdostream |
| : public std::ostream |
| { |
| protected: |
| fdoutbuf buf; |
| public: |
| explicit fdostream( int fd ) |
| : buf( fd ), std::ostream( &buf ) |
| {} |
| //... |
| }; |
| </pre></blockquote> |
| |
| <p>This is undefined because C++'s initialization order mandates that |
| the base class is initialized before the member it uses. <a |
| href="http://www.moocat.org">R. Samuel Klatchko</a> developed a way |
| around this by using the initialization order in his favor. Base |
| classes are intialized in order of declaration, so moving the desired |
| member to another base class, that is initialized before the desired |
| base class, can ensure proper initialization.</p> |
| |
| <p>A custom base class can be made for this idiom:</p> |
| |
| <blockquote><pre> |
| #include <streambuf> <i>// for std::streambuf</i> |
| #include <ostream> <i>// for std::ostream</i> |
| |
| class fdoutbuf |
| : public std::streambuf |
| { |
| public: |
| explicit fdoutbuf( int fd ); |
| //... |
| }; |
| |
| struct fdostream_pbase |
| { |
| fdoutbuf sbuffer; |
| |
| explicit fdostream_pbase( int fd ) |
| : sbuffer( fd ) |
| {} |
| }; |
| |
| class fdostream |
| : private fdostream_pbase |
| , public std::ostream |
| { |
| typedef fdostream_pbase pbase_type; |
| typedef std::ostream base_type; |
| |
| public: |
| explicit fdostream( int fd ) |
| : pbase_type( fd ), base_type( &sbuffer ) |
| {} |
| //... |
| }; |
| </pre></blockquote> |
| |
| <p>Other projects can use similar custom base classes. The technique |
| is basic enough to make a template, with a sample template class in |
| this library. The main template parameter is the type of the enclosed |
| member. The template class has several (explicit) constructor member |
| templates, which implicitly type the constructor arguments and pass them |
| to the member. The template class uses implicit copy construction and |
| assignment, cancelling them if the enclosed member is non-copyable.</p> |
| |
| <p>Manually coding a base class may be better if the construction |
| and/or copying needs are too complex for the supplied template class, |
| or if the compiler is not advanced enough to use it.</p> |
| |
| <p>Since base classes are unnamed, a class cannot have multiple (direct) |
| base classes of the same type. The supplied template class has an |
| extra template parameter, an integer, that exists solely to provide type |
| differentiation. This parameter has a default value so a single use of a |
| particular member type does not need to concern itself with the integer.</p> |
| |
| <h2><a name="synopsis">Synopsis</a></h2> |
| |
| <blockquote><pre> |
| #ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY |
| #define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10 |
| #endif |
| |
| template < typename MemberType, int UniqueID = 0 > |
| class boost::base_from_member |
| { |
| protected: |
| MemberType member; |
| |
| base_from_member(); |
| |
| template< typename T1 > |
| explicit base_from_member( T1 x1 ); |
| |
| template< typename T1, typename T2 > |
| base_from_member( T1 x1, T2 x2 ); |
| |
| //... |
| |
| template< typename T1, typename T2, typename T3, typename T4, |
| typename T5, typename T6, typename T7, typename T8, typename T9, |
| typename T10 > |
| base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, |
| T8 x8, T9 x9, T10 x10 ); |
| }; |
| </pre></blockquote> |
| |
| <p>The class template has a first template parameter |
| <var>MemberType</var> representing the type of the based-member. |
| It has a last template parameter <var>UniqueID</var>, that is an |
| <code>int</code>, to differentiate between multiple base classes that use |
| the same based-member type. The last template parameter has a default |
| value of zero if it is omitted. The class template has a protected |
| data member called <var>member</var> that the derived class can use |
| for later base classes (or itself).</p> |
| |
| <p>There is a default constructor and several constructor member |
| templates. These constructor templates can take as many arguments |
| (currently up to ten) as possible and pass them to a constructor of |
| the data member. Since C++ does not allow any way to explicitly state |
| the template parameters of a templated constructor, make sure that |
| the arguments are already close as possible to the actual type used in |
| the data member's desired constructor.</p> |
| |
| <p>The <var>BOOST_BASE_FROM_MEMBER_MAX_ARITY</var> macro constant specifies |
| the maximum argument length for the constructor templates. The constant |
| may be overridden if more (or less) argument configurations are needed. The |
| constant may be read for code that is expandable like the class template and |
| needs to maintain the same maximum size. (Example code would be a class that |
| uses this class template as a base class for a member with a flexible set of |
| constructors.)</p> |
| |
| <h2><a name="usage">Usage</a></h2> |
| |
| <p>With the starting example, the <code>fdoutbuf</code> sub-object needs |
| to be encapsulated in a base class that is inheirited before |
| <code>std::ostream</code>.</p> |
| |
| <blockquote><pre> |
| #include <boost/utility/base_from_member.hpp> |
| |
| #include <streambuf> <i>// for std::streambuf</i> |
| #include <ostream> <i>// for std::ostream</i> |
| |
| class fdoutbuf |
| : public std::streambuf |
| { |
| public: |
| explicit fdoutbuf( int fd ); |
| //... |
| }; |
| |
| class fdostream |
| : private boost::base_from_member<fdoutbuf> |
| , public std::ostream |
| { |
| // Helper typedef's |
| typedef boost::base_from_member<fdoutbuf> pbase_type; |
| typedef std::ostream base_type; |
| |
| public: |
| explicit fdostream( int fd ) |
| : pbase_type( fd ), base_type( &member ) |
| {} |
| //... |
| }; |
| </pre></blockquote> |
| |
| <p>The base-from-member idiom is an implementation detail, so it |
| should not be visible to the clients (or any derived classes) of |
| <code>fdostream</code>. Due to the initialization order, the |
| <code>fdoutbuf</code> sub-object will get initialized before the |
| <code>std::ostream</code> sub-object does, making the former |
| sub-object safe to use in the latter sub-object's construction. Since the |
| <code>fdoutbuf</code> sub-object of the final type is the only sub-object |
| with the name "member," that name can be used |
| unqualified within the final class.</p> |
| |
| <h2><a name="example">Example</a></h2> |
| |
| <p>The base-from-member class templates should commonly involve |
| only one base-from-member sub-object, usually for attaching a |
| stream-buffer to an I/O stream. The next example demonstrates how |
| to use multiple base-from-member sub-objects and the resulting |
| qualification issues.</p> |
| |
| <blockquote><pre> |
| #include <boost/utility/base_from_member.hpp> |
| |
| #include <cstddef> <i>// for NULL</i> |
| |
| struct an_int |
| { |
| int y; |
| |
| an_int( float yf ); |
| }; |
| |
| class switcher |
| { |
| public: |
| switcher(); |
| switcher( double, int * ); |
| //... |
| }; |
| |
| class flow_regulator |
| { |
| public: |
| flow_regulator( switcher &, switcher & ); |
| //... |
| }; |
| |
| template < unsigned Size > |
| class fan |
| { |
| public: |
| explicit fan( switcher ); |
| //... |
| }; |
| |
| class system |
| : private boost::base_from_member<an_int> |
| , private boost::base_from_member<switcher> |
| , private boost::base_from_member<switcher, 1> |
| , private boost::base_from_member<switcher, 2> |
| , protected flow_regulator |
| , public fan<6> |
| { |
| // Helper typedef's |
| typedef boost::base_from_member<an_int> pbase0_type; |
| typedef boost::base_from_member<switcher> pbase1_type; |
| typedef boost::base_from_member<switcher, 1> pbase2_type; |
| typedef boost::base_from_member<switcher, 2> pbase3_type; |
| |
| typedef flow_regulator base1_type; |
| typedef fan<6> base2_type; |
| |
| public: |
| system( double x ); |
| //... |
| }; |
| |
| system::system( double x ) |
| : pbase0_type( 0.2 ) |
| , pbase1_type() |
| , pbase2_type( -16, &this->pbase0_type::member ) |
| , pbase3_type( x, static_cast<int *>(NULL) ) |
| , base1_type( pbase3_type::member, pbase1_type::member ) |
| , base2_type( pbase2_type::member ) |
| { |
| //... |
| } |
| </pre></blockquote> |
| |
| <p>The final class has multiple sub-objects with the name |
| "member," so any use of that name needs qualification by |
| a name of the appropriate base type. (Using <code>typedef</code>s |
| ease mentioning the base types.) However, the fix introduces a new |
| problem when a pointer is needed. Using the address operator with |
| a sub-object qualified with its class's name results in a pointer-to-member |
| (here, having a type of <code>an_int boost::base_from_member<an_int, |
| 0> :: *</code>) instead of a pointer to the member (having a type of |
| <code>an_int *</code>). The new problem is fixed by qualifying the |
| sub-object with "<code>this-></code>," and is needed just |
| for pointers, and not for references or values.</p> |
| |
| <p>There are some argument conversions in the initialization. The |
| constructor argument for <code>pbase0_type</code> is converted from |
| <code>double</code> to <code>float</code>. The first constructor |
| argument for <code>pbase2_type</code> is converted from <code>int</code> |
| to <code>double</code>. The second constructor argument for |
| <code>pbase3_type</code> is a special case of necessary conversion; all |
| forms of the null-pointer literal in C++ also look like compile-time |
| integral expressions, so C++ always interprets such code as an integer |
| when it has overloads that can take either an integer or a pointer. The |
| last conversion is necessary for the compiler to call a constructor form |
| with the exact pointer type used in <code>switcher</code>'s constructor.</p> |
| |
| <h2><a name="credits">Credits</a></h2> |
| |
| <h3><a name="contributors">Contributors</a></h3> |
| |
| <dl> |
| <dt><a href="http://www.boost.org/people/ed_brey.htm">Ed Brey</a> |
| <dd>Suggested some interface changes. |
| |
| <dt><a href="http://www.moocat.org">R. Samuel Klatchko</a> (<a |
| href="mailto:rsk@moocat.org">rsk@moocat.org</a>, <a |
| href="mailto:rsk@brightmail.com">rsk@brightmail.com</a>) |
| <dd>Invented the idiom of how to use a class member for initializing |
| a base class. |
| |
| <dt><a href="http://www.boost.org/people/dietmar_kuehl.htm">Dietmar Kuehl</a> |
| <dd>Popularized the base-from-member idiom in his |
| <a href="http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/">IOStream |
| example classes</a>. |
| |
| <dt>Jonathan Turkanis |
| <dd>Supplied an implementation of generating the constructor templates that |
| can be controlled and automated with macros. The implementation uses |
| the <a href="../preprocessor/index.html">Preprocessor library</a>. |
| |
| <dt><a href="http://www.boost.org/people/daryle_walker.html">Daryle Walker</a> |
| <dd>Started the library. Contributed the test file <cite><a |
| href="base_from_member_test.cpp">base_from_member_test.cpp</a></cite>. |
| </dl> |
| |
| <hr> |
| |
| <p>Revised: 28 August 2004</p> |
| |
| <p>Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and distribution |
| are subject to the Boost Software License, Version 1.0. (See accompanying |
| file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a copy at <<a |
| href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>>.)</p> |
| |
| </body> |
| </html> |