Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This solution has a number of disadvantages which makes it sub optimal in my mind. Most of it comes down to the fact that the TypeList becomes a major compilation bottleneck, in the same way the switch case would've been. In my experience doWrite / doDelete in this example is better solved by virtual dispatch, but the actual object creation needs the mapping of runtime data to the concrete type. The best solution for this, imo, is to just go for a factory. If you have <a href="http://loki-lib.sourceforge.net/" rel="nofollow">Loki</a> it's as simple as:</p> <pre><code>// BaseFactory.h typedef Loki::SingletonHolder&lt; Loki::Factory&lt; Base, std::string &gt; &gt; BaseFactory; #define REGISTER_BASE_FACTORY( x ) \ static bool BOOST_PP_CAT( registerBaseFac, x ) = BaseFactory::Instance().Register( BOOST_PP_STRINGIZE( x ), boost::phoenix::new_&lt; x &gt;() ); // For example A.cpp REGISTER_BASE_FACTORY( x ); // Somewhere else ... Base* someInstance = BaseFactory::Instance().CreateObject("A"); assert( typeid( *someInstance ) == typeid( A ) ); ... </code></pre> <p>Personally I use a different factory base which is more akin to:</p> <pre><code>#pragma once #include "boost/unordered_map.hpp" #include &lt;cassert&gt; template&lt; typename KeyType, typename ProductCreatorType &gt; class Factory { typedef boost::unordered_map&lt; KeyType, ProductCreatorType &gt; CreatorMap; public: const ProductCreatorType&amp; operator()( const KeyType&amp; a_Key ) const { typename CreatorMap::const_iterator itrFnd = m_Creators.find( a_Key ); assert( itrFnd != m_Creators.end() ); return itrFnd-&gt;second; } ProductCreatorType&amp; operator()( const KeyType&amp; a_Key ) { typename CreatorMap::iterator itrFnd = m_Creators.find( a_Key ); assert( itrFnd != m_Creators.end() ); return itrFnd-&gt;second; } bool RegisterCreator( const KeyType&amp; a_Key, const ProductCreatorType&amp; a_Creator ) { return m_Creators.insert( std::make_pair( a_Key, a_Creator ) ).second; } private: CreatorMap m_Creators; }; </code></pre> <p>Simply because of the fact that it's more flexible ( able to handle for example returning <code>boost::shared_ptr&lt;&gt;</code> ).</p> <p>The major advantage of this approach is that you can have the registration code in the same translation unit as the concrete type. Way easier to separate client &amp; library code and modifying a concrete type doesn't cause recompilation of everything that needs the factory. As a bonus the performance scale is better as well.</p> <p>If you don't want virtual dispatch, you can use the same approach, but instead use member function pointers and supply the instance, this can be solved with an almost identical approach using <code>boost::bind</code>.</p> <p>EDIT: So yeah, missed that you wanted it completely compile time based, although to be honest I don't quite see any benefits.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload