###  | # Serialization ## `extended_type_info`

Motivation
Runtime Interface
Requirements
Models

### Motivation

The serialization library needs a system like `type_info/typeid()` to perform the following functions

1. given a pointer to a type T discover the true type pointed to.
2. given an "external" key - determine what type of object to create.

### The problem with `std::type_info`

- The main function we require - `std::typeid()` 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.
- `std::type_info` 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.
- Even if the type name string could somehow be made portable, there is no guarentee that class headers would be included in the same name space accross different applications. In fact, including different headers in different name spaces is an accepted method used to avoid name space conflicts. Thus the namespace::class_name can't be used as a key.
- We may want the ability to serialize objects through a base class even though they have no `virtual` function. That is, objects of classes which are not polymorphic in the strict C++ sense. This is not supported by the standard system.
- There exists the possibility that different classes use different type id mechanism. The class header might include this information. If we want to import class headers accross applications, its convenient that the type id mechanism support inter-operability accross different type id systems.

### Features

`extended_type_info` is an implementation of `std::type_info` functionality with the following features:

- Maintains a global table of `extended_type_info` records - one for each type known to the program.
- permits association of an arbitrary 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.
- permits the "mixing" of type info systems. For example, one class might use `typeid()` to find the external identifier of a class while another might not.

The serialization system maintains two global tables.

- The first is a global type table. it and has with an entry for each type used. Each entry is an instance of a class derived from `extended_type_info`. This table is used to retrieve the unique `extended_type_info` information for any given type.
- The second is global key table. It has an entry for each type which has been assigned a GUID string key. This table is used to retrieve the unique `extended_type_info` given its GUID.

This library includes two different type id systems:

- `extended_type_info_typeid` which is implemented in terms of the standard `typeid()`.
- `extended_type_info_no_rtti` which is implemented in a way that doesn't rely on the existence RTTI. However, it does require that all classes for which type id is to be used be explictly assigned an external key - which otherwise would be optional.

### Runtime Interface

    namespace boost {
    namespace serialization {

    class BOOST_SERIALIZATION_DECL extended_type_info :
        private boost::noncopyable
    {
    protected:
        extended_type_info(const char * type_info_key);
    public:
        void self_register();
        void key_register(const char *key);
        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;

        static const extended_type_info * find(const char *key);
        static const extended_type_info * find(const extended_type_info * t);
    };

    } // namespace serialization
    } // namespace boost

There must be one and only one `extended_type_info` instance created for each type. For this reason, this class is marked is derived from `boost::noncopyable`.

####

    extended_type_info(const char * type_info_key);

  This constructor should be called by all derived classes. It should be passed a pointer to a const string which identifies the type id system being used. This type id is used to distinguish among the various type id system that might be used and allow them to interoperate.

####

    void self_register();

  This function adds entry for an entry to the global type table. It would usually be called from the constructor of the derived class which implements the `extended_type_info` functionality.

####

    void key_register(const char *key);

  Assign a unique character string identifier to this `extended_type_info` instance and add it to the corresponding global trable. This key is used to identify a type accross different instances of the program. In this way, one instance may know what type to create when necessary. For this purpose, it must be the same in all program instances which refer to the same type.

  It may sometimes be referred to as a GUID - a Global Unique IDentifier.

####

    const char *get_key() const;

  Retrieves the key for `extended_type_info` instance. If no key has been associated with the instance, then a NULL is returned.

####

    bool operator<(const extended_type_info &rhs) const;
    bool operator==(const extended_type_info &rhs) const;
    bool operator!=(const extended_type_info &rhs) const;

  These functions are used to compare two `extended_type_info` objects. Among other things, these are used for lookup in the tables.

####

    static const extended_type_info * find(const char *key);

  Given a character string key or GUID, return the address of the unique corresponding `extended_type_info` object.

####

    static const extended_type_info * find(const extended_type_info * t);

  Given a pointer to an `extended_type_info`, return the address of the instance of the same type in the main table. That is the argument t is used as a search argment to find the main table entry for a given type. It would be used like this: `

      // return the global type entry for our type T
      return find(some_extended_type_info_implementation<T>())

  `

### Requirements

In order to be used by the serialization library, an implementation of `extended_type_info`, (referred to as ETI here), must implement the following:

#### `

    template<class ETI>
    virtual bool
    ETI::less_than(const extended_type_info &rhs) const;

`

  Impose a strict total ordering on all instances of the class ETI.

#### `

    template<class ETI>
    static const extended_type_info *
    ETI::get_derived_extended_type_info(const T & t);

`

  Return a pointer to the `extended_type_info` 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. Implemention 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 `extended_type_info implementation`.

#### `

    template<class ETI>
    static extended_type_info *
    ETI::get_instance();

`

  Return a pointer to the instance of `extended_type_info` which corresponds to type T. Normally these instances are static objects so this just amounts to returning the address of this static object.

#### `

    static void
    template<class ETI>
    ETI::export_register(const char * key);

`

  The main function is to invoke key_register to add the GUID to the global table. Depending on the type id system being used, it might perform other initializaition functions as well.

It must define the following Itegral Constant of type bool:

#### `

    ETI::is_polymorphic

`

### Models

The serialization library includes two distinct `extended_type_info` implementations.

``

#### extended_type_info_typeid

is implemented in terms of the standard typeid(). It presumes that RTTI support is enabled by the compiler.

``

#### extended_type_info_no_rtti

is implemented in a way that doesn't rely on the existence RTTI. However, it does require that all classes for which type id is to be used implement a virtual function of the signiture: `

    virtual const char * get_key();

` which returns a unique string the most derived object this class. This function must be virtual in order to implement the functionality required by `ETI::get_derived_extended_type_info` as described above. The test program `test_no_rtti` implements this function in terms of the `extended_type_info` API above to return the export key associated with the class. This requires that non-abstract types be exported.

© Copyright Robert Ramey 2005. 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)