123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- <!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <!--
- (C) Copyright 2002-4 Robert Ramey - http://www.rrsd.com .
- Use, modification and distribution is subject to the Boost Software
- License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt)
- -->
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <link rel="stylesheet" type="text/css" href="../../../boost.css">
- <link rel="stylesheet" type="text/css" href="style.css">
- <title>Serialization - extended_type_info</title>
- </head>
- <body link="#0000ff" vlink="#800080">
- <table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header">
- <tr>
- <td valign="top" width="300">
- <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../boost.png" border="0"></a></h3>
- </td>
- <td valign="top">
- <h1 align="center">Serialization</h1>
- <h2 align="center"><code style="white-space: normal">extended_type_info</code></h2>
- </td>
- </tr>
- </table>
- <hr>
- <dl class="page-index">
- <dt><a href="#motivation">Motivation</a>
- <dt><a href="#runtime">Runtime Interface</a>
- <dt><a href="#requirements">Requirements</a>
- <dt><a href="#models">Models</a>
- <dt><a href="#example">Example</a>
- </dl>
- <h3><a name="motivation">Motivation</a></h3>
- The serialization library needs a system like
- <code style="white-space: normal">type_info/typeid()</code> to perform
- the following functions
- <ol>
- <li>
- given a pointer to a type T discover the true type pointed to.
- <li>
- given an "external" key - determine what type of object to create.
- </ol>
- <h3>The problem with <code style="white-space: normal">std::type_info</code></h3>
- <ul>
- <li>
- The main function we require - <code style="white-space: normal">std::typeid()</code>
- is not available in all environments. Support for this function depends upon
- runtime typing(RTTI) support from the compiler. This may be non-existent
- or not enabled for reasons such as a percieved inefficiency.
- <li>
- <code style="white-space: normal">std::type_info</code> includes a string
- containing type name. This would seem to satisfy 2) above.
- But the format of this string is not consistent accross compilers, libraries,
- and operating systems. This makes it unusable for support of portable archives.
- <li>
- Even if the type name string could somehow be made portable, there is no
- guarantee that class headers would be included in the same namespace accross
- different applications. In fact, including different headers in different
- namespaces is an accepted method used to avoid namespace conflicts.
- Thus the namespace::class_name can't be used as a key.
- <li>
- There exists the possibility that different classes use different type id
- mechanisms. The class header might include this information. If we want to
- import class headers accross applications, it's convenient that the type id
- mechanism support inter-operability accross different type id systems.
- </ul>
- <h3>Features</h3>
- <code style="white-space: normal"><a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp">
- extended_type_info</a></code> is an implementation
- of <code style="white-space: normal">std::type_info</code> functionality with the
- following features:
- <ul>
- <li>
- Builds a set of <a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp">
- <code style="white-space: normal">extended_type_info</a></code> records - one for each type
- serialized.
- <li>
- permits association of an arbitrary string key with a type. Often this key would
- be the class name - but it doesn't have to be. This key is referred to as
- a GUID - Globally Unique IDentifier. Presumably it should be unique in the universe.
- Typically this GUID would be in header files and be used to match type accross
- applications. The macro BOOST_CLASS_EXPORT can be invoked to associate a string
- key with any known type. We'll refer to these types as "exported types"
- <li>
- permits the "mixing" of type info systems. For example, one class might use
- <code style="white-space: normal">typeid()</code> to find the external identifier
- of a class while another might not.
- </ul>
- Exported types are maintained in a global table so that given a string key, the
- corresponding type can be found. This facility is used by the serialization library
- in order to construct types serialized through a base class pointer.
- <h3><a name="runtime">Runtime Interface</a></h3>
- <pre><code">
- namespace boost {
- namespace serialization {
- class extended_type_info
- {
- protected:
- // this class can't be used as is. It's just the
- // common functionality for all type_info replacement
- // systems. Hence, make these protected
- extended_type_info(
- const unsigned int type_info_key,
- const char * key
- );
- ~extended_type_info();
- void key_register();
- void key_unregister();
- public:
- const char * get_key() const;
- bool operator<(const extended_type_info &rhs) const;
- bool operator==(const extended_type_info &rhs) const;
- bool operator!=(const extended_type_info &rhs) const {
- return !(operator==(rhs));
- }
- // for plugins
- virtual void * construct(unsigned int count = 0, ...) const;
- virtual void destroy(void const * const p) const;
- static const extended_type_info * find(const char *key);
- };
- } // namespace serialization
- } // namespace boost
- </code></pre>
- <p>
- Generally, there will be one and only one
- <code style="white-space: normal"><a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp">extended_type_info</a></code>
- instance created for each type. However, this is enforced only at the executable
- module level. That is, if a program includes some shared libraries or DLLS,
- there may be more than one instance of this class correponding to a particular type.
- For this reason the comparison functions below can't just compare the addresses of
- this instance but rather must be programmed to compare the actual information
- the instances contain.
- <dl>
- <dt><h4><pre><code>
- extended_type_info(unsigned int type_info_key, const char *key);
- </code></pre></h4></dt>
- <dd>
- This constructor should be called by all derived classes.
- The first argument should be the particular implementation.
- For this default implementation base on typeid(), this is the
- value 1. Each system must have its own integer. This value
- is used to permit the inter-operability of different typeinfo
- systems.
- <p>
- The second argument is a const string which is the external
- name of the type to which this record corresponds.
- It may sometimes be referred to as a GUID - a <b>G</b>lobal <b>U</b>nique <b>ID</b>entifier.
- It is passed through archives from one program invocation to
- another to uniquely identify the types that the archive contains.
- If the "export" facility is not going to be used,
- this value may be NULL.
- </dd>
- <dt><h4><pre><code>
- void key_register();
- void key_unregister();
- </code></pre></h4></dt>
- <dd>
- This system maintains a global table which relates
- external strings to
- <code style="white-space: normal">extended_type_info</code> records.
- This table is used when loading pointers to objects serialized
- through a base class pointer. In this case, the archive
- contains a string which is looked up in this table to
- determine which <code style="white-space: normal">extended_type_info</code>
- to use for creating a new object.
- <p>
- These functions are called by constructors and
- destructors of classes which implement
- <code style="white-space: normal">extended_type_info</code>
- to add and remove entries from this table.
- </dd>
- <dt><h4><pre><code>
- const char *get_key() const;
- </code></pre></h4></dt>
- <dd>
- Retrieves the key for <code style="white-space: normal"><a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp">extended_type_info</a></code>
- instance. If no key has been associated with the instance, then a NULL is returned.
- </dd>
- <dt><h4><pre><code>
- bool operator<(const extended_type_info & rhs) const;
- bool operator==(const extended_type_info & rhs) const;
- bool operator!=(const extended_type_info & rhs) const;
- </code></pre></h4></dt>
- <dd>
- These functions are used to compare
- <a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp">
- <code style="white-space: normal">
- extended_type_info
- </code>
- </a>
- objects. They impose a strict total ordering on all
- <code style="white-space: normal">extended_type_info</code> records.
- </dd>
- <dt><h4><pre><code>
- virtual void * construct(unsigned int count = 0, ...) const;
- </code></pre></h4></dt>
- <dd>
- Construct a new instance of the type to which this
- <a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp">
- <code style="white-space: normal">
- extended_type_info
- </code>
- </a>
- record corresponds. This function takes a variable list of up to 4 arguments
- of any type. These arguments are passed to the type's constructor
- at runtime. In order to use the facility,
- one must declare a type sequence for the constructor arguments.
- Arguments for this function must match in number and type
- with those specified when the type was exported.
- This function permits one to create instances of
- any exported type given only the exported <strong>GUID</strong> assigned
- with BOOST_CLASS_EXPORT.
- If these types are defined in DLLS or shared libraries loaded at runtime,
- these constructors can be called until the module is unloaded.
- Such modules are referred to as <b>plugins</b>.
- </code>
- </dd>
- <dt><h4><pre><code>
- virtual void destroy(void const * const p) const;
- </code></pre></h4></dt>
- <dd>
- Destroy an instance created by the above constructor.
- </dd>
- <dt><h4><pre><code>
- static const extended_type_info * find(const char *key);
- </code></pre></h4></dt>
- <dd>
- Given a character string key or <strong>GUID</strong>, return the address of a
- corresponding <code style="white-space: normal"><a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp">extended_type_info</a></code>
- object.
- </dl>
- <h3><a name="requirements">Requirements for an Implementation</a></h3>
- In order to be used by the serialization library, an implementation of
- <code style="white-space: normal">extended_type_info</code>,
- (referred to as ETI here), must be derived from
- <a target="extended_type_info.hpp" href = "../../../boost/serialization/extended_type_info.hpp">
- <code style="white-space: normal">
- extended_type_info
- </code>
- </a>
- and also implement the following:
- <dl>
- <dt><h4><code style="white-space: normal"><pre>
- template<class ETI>
- const extended_type_info *
- ETI::get_derived_extended_type_info(const T & t) const;
- </pre></code></h4></dt>
- <dd>
- Return a pointer to the
- <code style="white-space: normal">extended_type_info</code>
- instance that corresponds to
- the "true type" of the type T. The "true type" is the lowest type in the
- hierarchy of classes. The type T can always be cast to the "true type" with
- a static cast. Implementation of this function will vary among type id systems
- and sometimes will make presumptions about the type T than can be identified
- with a particular <code style="white-space: normal">extended_type_info</code> implementation.
- </dd>
- <dt><h4><code style="white-space: normal"><pre>
- virtual bool ETI::is_less_than(const extended_type_info &rhs) const;
- </pre></code></h4></dt>
- <dd>
- Compare this instance to another one using the same
- <code style="white-space: normal">extended_type_info</code> implementation.
- </dd>
- <dt><h4><code style="white-space: normal"><pre>
- virtual bool ETI::is_equal(const extended_type_info &rhs) const;
- </pre></code></h4></dt>
- <dd>
- Compare this instance to another one using the same
- <code style="white-space: normal">extended_type_info</code> implementation.
- Return <code style="white-space: normal">true</code> if the types referred
- to are the same. Otherwise return
- <code style="white-space: normal">false</code>
- </dd>
- <dt><h4><code style="white-space: normal"><pre>
- const char ETI::get_key() const;
- </pre></code></h4></dt>
- <dd>
- Retrieve the external key (aka GUID) for this class.
- </dd>
- <dt><h4><code style="white-space: normal"><pre>
- virtual void * construct(unsigned int count, ...) const;
- </pre></code></h4></dt>
- <dd>
- Construct an instance of the corresponding type
- with the include argument list.
- </dd>
- <dt><h4><code style="white-space: normal"><pre>
- virtual void * destroy(void const * const ptr ) const;
- </pre></code></h4></dt>
- <dd>
- Destroy an instance of this type. This calls the
- proper destructor and recovers allocated memory.
- </dd>
- </dl>
- <h3><a name="models">Models</a></h3>
- The serialization library includes two distinct
- <code style="white-space: normal"><a target="extended_type_info.hpp" href="../../../boost/serialization/extended_type_info.hpp">extended_type_info</a></code>
- implementations.
- <p>
- <code style="white-space: normal"><h4><a target="extended_type_info_typeid.hpp" href = "../../../boost/serialization/extended_type_info_typeid.hpp">
- extended_type_info_typeid</a></h4></code>is implemented in terms of the standard typeid(). It presumes that RTTI support is enabled
- by the compiler.
- <p>
- <code style="white-space: normal"><h4><a target="extended_type_info_no_rtti.hpp" href="../../../boost/serialization/extended_type_info_no_rtti.hpp">
- extended_type_info_no_rtti</a></h4></code>
- is implemented in a way that doesn't rely on the existence RTTI.
- Instead, it requires that all polymorphic types be explictly exported.
- In addition, if the export facility is to be used to serialize types
- through base class pointers, those types are required to implement
- a virtual function with the signature:
- <code><pre>
- virtual const char * get_key();
- </pre></code>
- which returns a unique string the most derived object this class.
- This function must be virtual in order to implement the functionality required by
- <code style="white-space: normal">ETI::get_derived_extended_type_info</code>
- as described above.
- <h3><a name="example">Example</a></h3>
- The test program <code style="white-space: normal"><a target="test_no_rtti" href="../test/test_no_rtti.cpp">test_no_rtti</a></code>
- implements this function in terms of the <code style="white-space: normal"><a target="extended_type_info_no_rtti.hpp" href="../../../boost/serialization/extended_type_info_no_rtti.hpp">
- extended_type_info</a></code> API above to return the export key associated with the class.
- This requires that non-abstract types be exported. It also demonstrates the
- inter-operability between two different implementations of
- <code style="white-space: normal">extended_type_info</code>.
- <h3><a name="type_requirements">Requirements for Each Type</a></h3>
- Each type to be managed by the system must be
- "registered" individually. This is accomplished by instantiating
- templates. For example, if the type T is to use the type_info system
- one would include the following code:
- <code style="white-space: normal"><pre>
- namespace boost {
- namespace serialization {
- template
- struct extended_type_info_typeid>T>;
- template
- struct extended_type_info_typeid>const T>;
- } // serialization
- } // boost
- </pre></code>
- For those using the serialization library, this step can be skipped
- as it is done automatically. The serialization library includes
- the macro:
- <code style="white-space: normal"><pre>
- BOOST_CLASS_TYPE_INFO(
- my_type,
- extended_type_info_typeid>my_class>
- )
- </pre></code>
- which is used to specify which <code>extended_type_info</code> system is to
- be used for a given type.
- <p>
- <code>extended_type_info</code> includes a facility for constructing
- instances of types without knowing what the exact types are. This is done
- with the function
- <code>
- virtual void * extended_type_info::construct(unsigned int count = 0, ...) const;
- </code>
- . For example:
- <br>
- <code><pre>
- struct base {
- ...
- };
- struct derived : public base {
- ...
- };
- ...
- extended_type_info *eti = extended_type_info::find("my_class")
- base * b = eti->construct(...);
- </pre></code>
- <br>
- The <code>construct</code> takes an argument count and up to
- four parameters of any type. The arguments are passed to the
- constructor of "my_class".
- A complete example of this can be found
- <a target="test_dll_plugin.cpp" href="../test/test_dll_plugin.cpp">here</a>
- <hr>
- <p><i>© Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2005-2009.
- Distributed under the Boost Software License, Version 1.0. (See
- accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- </i></p>
- </body>
- </html>
|