1 June 2013

ZipLib, the lightweight C++11 library for working with ZIP archives

ZipLib is a lightweight C++11 library for working with ZIP archives with ease. The very useful feature of ZipLib is that it is built around STL streams, no additional dependencies (boost) are required. You may find the project on the bitbucket here.

Features

  • Compression/decompresion using the DEFLATE algorithm
  • Storing/fetching files without compression
  • Adding, editing and removing files and directories in the archive
  • Support of the data descriptor
  • Data flow is driven via STL streams, therefore there is no need to load huge amount of data into the memory
  • Support of PKWare encryption
  • Support of entry comments and archive comments
  • Contains very usable stream classes in the ZipLib/streams folder, like memory stream, substream or teestream
  • Contains functions for easy (de)serialization (ZipLib/streams/serialization.h)
  • Project is using only C++11 standard libraries, therefore there IS NO dependency on 3rd party libraries (except of included zlib, which uses standard libraries of C afterall :))
  • Built around smart pointers
  • Support of Windows and Linux

Example of usage

Adding, extracting and removing file using ZipFile wrapper
  const char* zipFilename = "archive.zip";
  ZipFile::AddFile(zipFilename, "file.txt");

  // there is no need to create folders in the archive separately, because they are part of the filename
  ZipFile::AddEncryptedFile(zipFilename, "fileOnDisk.txt", "destination/in/archive.txt", "password");

  ZipFile::ExtractFile(zipFilename, "file.txt", "newFileOnDisk.txt");

  ZipFile::ExtractEncryptedFile(zipFilename, "destination/in/archive.txt", "encrypted.txt", "password");

  // because folders are part of the filename (until they are not created separately),
  // the "destination" and "in" folders are deleted too
  ZipFile::RemoveEntry(zipFilename, "destination/in/archive.txt");


Very basic sample of a file compression
  ZipArchive::Ptr archive = ZipFile::Open("archive.zip");

  ZipArchiveEntry::Ptr entry = archive->CreateEntry("file.dat");

  // if entry is nullptr, it means the file already exists in the archive
  assert(entry != nullptr); 

  std::ifstream contentStream("file.dat", std::ios::binary);
  entry->SetCompressionStream(contentStream);

  // you may of course save it somewhere else
  // note: the contentStream is pumped when the archive is saved
  // if you want to read the stream before saving of the archive,
  // it is need to set Immediate mode in SetCompressionStream method (see below)
  ZipFile::SaveAndClose(archive, "archive.zip");


Very basic sample of a file decompression
  ZipArchive::Ptr archive = ZipFile::Open("archive.zip");

  ZipArchiveEntry::Ptr entry = archive->GetEntry("file.txt");

  // if the entry is password protected, it is necessary
  // to set the password before getting a decompression stream
  if (entry->IsPasswordProtected())
  {
    // when decompressing an encrypted entry
    // there is no need to specify the use of data descriptor
    // (ZibLib will deduce if the data descriptor was used)
    entry->SetPassword("pass");
  }

  // if the entry is password protected and the provided password is wrong
  // (or none is provided) the return value will be nullptr
  std::istream* decompressStream = entry->GetDecompressionStream();

  std::string line;
  std::getline(*decompressStream, line);

  printf("First line of a file: '%s'\n", line.c_str());


Compressing a file with immediate mode
  auto archive = ZipFile::Open("archive.zip");

  auto entry = archive->CreateEntry("file.dat");

  // if entry is nullptr, it means the file already exists in the archive
  assert(entry != nullptr); 

  {
    std::ifstream contentStream("file.dat", std::ios::binary);
    entry->SetCompressionStream(   // data from contentStream are pumped here (into the memory)
      contentStream,
      ZipArchiveEntry::CompressionLevel::Default,
      ZipArchiveEntry::CompressionMethod::Deflate,
      ZipArchiveEntry::CompressionMode::Immediate
    );

    // the contentStream is destroyed here
  }

  ZipFile::SaveAndClose(archive, "archive.zip");


Compress and encrypt the memory stream
  char buffer[] = "A content to encrypt";
  imemstream contentStream(buffer); // imemstream is located in Source/ZipLib/streams

  auto archive = ZipFile::Open("archive.zip");
  auto entry = archive->CreateEntry("file.dat");

  entry->SetPassword("pass");
  entry->UseDataDescriptor(); // read stream only once
  entry->SetCompressionStream(contentStream);

  ZipFile::SaveAndClose(archive, "archive.zip");

You may find more samples in the Source/Sample/Main.cpp file.

Description of compression

You may specify several options how the input stream will be stored in the archive.

Compression method

Second (optional) parameter of the ZipArchiveEntry::SetCompressionStream method. Default value is Deflate.
  • Deflate - a standard compression algorithm used for ZIP archives
  • Stored - no compression

Compression level

Third (optional) parameter of the ZipArchiveEntry::SetCompressionStream method. Default value is Default.
  • Stored - data from the input stream will not be compressed
  • BestSpeed - data will be compressed with respect to the speed
  • Default - data will be compressed with satisfying time/compression ratio
  • BestCompression - data will be compressed with respect to the compression

Compression mode

Fourth (optional) parameter of the ZipArchiveEntry::SetCompressionStream method. Default value is Deferred.
  • Deferred - the data is compressed when the ZIP archive is about to be saved. In other words, the stream instance of input data to be stored must exist when the ZIP archive will be saved. The advantage of deferred compression mode is that the compressed data needs not to be loaded into the memory, because they are streamed into the final output stream.
  • Immediate - the data is compressed immediately into the memory buffer. It is not recommended to use this method for large files. The advantage of immediate mode is that the input stream can be destroyed (i.e. by scope) even before the ZIP archive is saved.

Password

You may set the password with the ZipArchiveEntry::SetPassword method. Entry is not password protected by default.
  • The structure of ZIP archive allows you to protect some specific file entries in the ZIP archive and some not
  • If you want the whole ZIP archive to be password protected, you must set the password on each entry you add
  • If you want to add the password protected file entry using the immediate mode, it is needed to set password before the SetCompressionStream call
  • If you want to add the password protected file entry using the deferred mode, it is needed to set password before saving the archive

Data descriptor

You may force the use of the data descriptor with ZipArchiveEntry::UseDataDescriptor method.

In short: usage of data descriptor when encrypting the entry leads to the faster compression, because the input stream is read only once, but there may be compatibility issues with very old applications.

Explanation: Data descriptor is small chunk of information written after the compressed data. It is most useful when storing a password protected entries. When the password protected entry does not use it, the CRC32 value of the data is required before encryption of the file data begins (it is used for checking of the correct password when decrypting), which means the stream must be read in its entirety to compute the actual CRC32 before proceeding and then be read again to actually store data.

If the data descriptor is used, the "last write time" attribute of the entry is used for checking of the correct password, therefore the stream content will be processed only once and the CRC32 is written after the compressed data.

Note1: when you use CompressionMethod::Stored, the CompressionLevel::Stored is set automatically and vice versa.

Note2: data descriptor is not set by default

29 January 2013

Reimplementation of dynamic_cast in C++

This article will introduce one of the ways to effectively replace functionality of dynamic_cast. Presented source code will use the latest C++ specification (C++11), but with a little bit of limitation it is not a problem to rewrite the source code to C++03.

Casting of base class to derived class can be achieved in two ways in C++: by using static_cast if we are lucky enough and casting is still possible at compile time, or by using dynamic_cast, if we are having no luck and we have to resort to built-in RTTI and perform casting at runtime. One such example is the attempt to cast from a virtual base class.

Many programmers claim that the need of dynamic_cast is a sign of a bad application design. I slightly disagree and I will point to the existence of several cases when dynamic_cast is very useful.  Imagine that you are working with a logging function, which is designed to store information about individual events. An event can have its base class, say, Event, from which inherits every event class. Thanks to dynamic_cast we could get further information about events - we can cast event from its base class Event to a particular event class and then get more information about it.


In the introduction I wrote about a casting of virtual base class to the derived class. Many people try to avoid the virtual inheritance in C++ as much as they can, but it can be useful when you are writing a framework which is rich on interfaces. Personally, I proved in practice to follow the rule that each interface (or abstract class, if you want), which uses a different interface properties (and/or methods), inherits it virtually. Also, it is good practice to have a base class for all other classes, including the interfaces, such as ObjectMany well-known projects in C++ are actually programmed that way.

The reason of virtual inheritance is to avoid creating multiple instances of base classes. Model situation may be the case where there are classes in the project: Object, InputStream, OutputStream and IOStream, which uses the methods of the two previous classes, which also inherits from the Object class. If we wouldn't use virtual inheritance in InputStream and OutputStream, IOStream object would contain two instances of the Object class. Then, if we would try to call GetHandle() from the IOStream object, the compiler would report an error, since the method call is ambiguous, because it is present in both classes. With virtual inheritance, there is only one instance, shared across all objects within each class. This case is also called diamond inheritance.

Example of non-use virtual inheritance

Example of  use virual inheritance

As already stated, the problem occurs at the moment when you need to cast a virtual class to one of the derived classes - Object to any other class - because of virtual inheritance. This problem can be easily solved by using dynamic_cast. For those who is afraid of dynamic_cast for any reason, I will give an alternative way to reimplement the behavior of dynamic_cast, in compliance with certain rules.

Here is how could look the instance of the class IOStream in the memory - from this picture it is clear that there is no easy way to cast Object class to its superclass.

One of these rules actually is that there must be a fundamental base class from which inherits all the other classes, which we want dynamic cast apply to. The Object class, in our case. The main purpose of this class is to provide information about the derived class (its name) and a pair of methods To(const std::string&) - one const and one non-const - which will be used for casting based on the class name. The heart of the principle itself is the hash-table stored in the Object class. Its task is to maintain pointers to derived subclasses based on their names. Table must be marked as mutable, so that we can edit it from const methods.
class Object
{
    public:
        virtual ~Object();

        static const std::string& GetClassNameStatic();
        virtual const std::string& GetClassName() const;
    
        void* To(const std::string& className);
        const void* To(const std::string& className) const;

    private:
        mutable std::map<std::string, void*> _bases;
};
This proposal itself is obviously not sufficient. It is needed to provide a method for the registration of a derived class and the method for recursively crawling the whole hierarchy of inheritance. I divided the source code into two parts to make it easier to be understood.
class Object
{
    public:
        virtual ~Object() { }

        static const std::string& GetClassNameStatic()
        {
            static std::string className("Object");
            return className;
        }

        virtual const std::string& GetClassName() const
        {
            return GetClassNameStatic();
        }
    
        void* To(const std::string& className)
        {
            if (_bases.size() == 0)
            {
                RegisterAllSubclasses();
            }

            auto result = _bases.find(className);
            return (result != _bases.end() ? (*result).second : nullptr);
        }

        const void* To(const std::string& className) const
        {
            if (_bases.size() == 0)
            {
                RegisterAllSubclasses();
            }

            auto result = _bases.find(className);
            return (result != _bases.end() ? (*result).second : nullptr);
        }

    protected:
        void RegisterSubclass(const void* ptr, const std::string& className) const
        {
            _bases[className] = const_cast<void*>(ptr);
        }

        virtual void RegisterAllSubclasses() const
        {
            RegisterSubclass(static_cast<const void*>(this), Object::GetClassName());
        }

    private:
        mutable std::map<std::string, void*> _bases;
};
At first glance it is clear what the principle will be. The inheritance hierarchy is not created until To() method is called, which implies the advantage of that the table will not be created until it's needed. Use of the if (_bases.size() == 0)statement is safe, because there always is at least Object in the map.

We will override virtual methods RegisterAllSubclasses() and GetClassName() along with the new definition of a static method GetClassNameStatic() for forcing derived classes to register themselves and their bases. The importance of creating a new definition of the static methods will be explained later. InputStream class could then look like this:
class InputStream : virtual public Object
{
    public:
        static const std::string& GetClassNameStatic()
        {
            static std::string className("InputStream");
            return className;
        }

        virtual const std::string& GetClassName() const override
        {
            return GetClassNameStatic();
        }

        void Read();

    protected:
        virtual void RegisterAllSubclasses() const override
        {
            RegisterSubclass(static_cast<const void*>(this), InputStream::GetClassName());
            Object::RegisterAllSubclasses();
        }
};
It is important to state specific class names in the method RegisterAllSubclasses(). If they are not specified, it would call the overriden method by the most derived class (if InputStream inherit from class IOStream, method GetClassName() would always return IOStream class name). Then call the method RegisterAllSubclasses() on all the base classes, which again register their bases recursively. Method RegisterAllSubclasses() in the IOStream class then should look as follows:
        virtual void RegisterAllSubclasses() const override
        {
            RegisterSubclass(static_cast<const void*>(this), IOStream::GetClassName());
            InputStream::RegisterAllSubclasses();
            OutputStream::RegisterAllSubclasses();
        }
Writing these methods in each class separately, of course, is not convenient, so it is better to leave this job for macro. The macro will take the name of the current class and it will be followed by a list (variadic macro) of all base classes . The actual registration of base classes is kind of tricky - it uses variadic templates that C++11 introduced.
#define DEFINE_BASES(class, ...)                                                \
    static const std::string& GetClassNameStatic()                              \
    {                                                                           \
        static std::string className(#class);                                   \
        return className;                                                       \
    }                                                                           \
                                                                                \
    const std::string& GetClassName() const override                            \
    {                                                                           \
        return GetClassNameStatic();                                            \
    }                                                                           \
                                                                                \
    template <typename _empty>                                                  \
    void RegisterAllSubclasses() const                                          \
    {                                                                           \
                                                                                \
    }                                                                           \
                                                                                \
    template <typename _empty, typename T, typename... Args>                    \
    void RegisterAllSubclasses() const                                          \
    {                                                                           \
        T::RegisterAllSubclasses();                                             \
        RegisterAllSubclasses<void, Args...>();                                 \
    }                                                                           \
                                                                                \
    virtual void RegisterAllSubclasses() const override                         \
    {                                                                           \
        RegisterSubclass(static_cast<const void*>(this), class::GetClassName());\
        RegisterAllSubclasses<void, __VA_ARGS__>();                             \
    }
The principle is simple - base classes will be registered recursively . After the registration of all classes, the Args parameter will be empty and the recursion will terminate by calling "blank" template method template <typename _empty> void RegisterAllSubclasses(). For the above case, the class IOStream will process the call as follows:


Finally, there remains only one thing - the function for dynamic casting itself. Now comes the advantage of the defined static method for determining the name of the class. Function asks for a class name passed through the template through the static function GetClassNameStatic() and passes it to the method To(const std::string&). The method attempts to find a pointer to a specific subclass in the map, which if it is found, it will return it.
template <typename T>
T my_dynamic_cast(Object* ptr)
{
    return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
}

template <typename T>
T my_dynamic_cast(const Object* ptr)
{
    return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
}
Some of you know the std::remove_pointer<T> trait from the Boost library, but in C++11 it is included in the STL in the type_traits header file. The reason why the function is used is obvious - the function needs to get the data type of the class, while there is passed only a pointer to it through the function.

In conclusion, I will say that there are many proposals for expanding this project. Apart from speeding up the casting by the indexing based on the string hash (which makes this alternative up to 10x faster than standard dynamic_cast), this project should be extended into full own RTTI reimplementation.

Finally, the whole source code:
#include <iostream>
#include <string>
#include <map>
#include <type_traits>

#define DEFINE_BASES(class, ...)                                                \
    static const std::string& GetClassNameStatic()                              \
    {                                                                           \
        static std::string className(#class);                                   \
        return className;                                                       \
    }                                                                           \
                                                                                \
    const std::string& GetClassName() const override                            \
    {                                                                           \
        return GetClassNameStatic();                                            \
    }                                                                           \
                                                                                \
    template <typename _empty>                                                  \
    void RegisterAllSubclasses() const                                          \
    {                                                                           \
                                                                                \
    }                                                                           \
                                                                                \
    template <typename _empty, typename T, typename... Args>                    \
    void RegisterAllSubclasses() const                                          \
    {                                                                           \
        T::RegisterAllSubclasses();                                             \
        RegisterAllSubclasses<void, Args...>();                                 \
    }                                                                           \
                                                                                \
    virtual void RegisterAllSubclasses() const override                         \
    {                                                                           \
        RegisterSubclass(static_cast<const void*>(this), class::GetClassName());\
        RegisterAllSubclasses<void, __VA_ARGS__>();                             \
    }

class Object
{
    public:
        virtual ~Object() { }

        static std::string& GetClassNameStatic()
        {
            static std::string className("Object");
            return className;
        }

        virtual const std::string& GetClassName() const
        {
            return GetClassNameStatic();
        }

        void* To(const std::string& className) 
        {
            if (_bases.size() == 0)
            {
                RegisterAllSubclasses();
            }

            auto result = _bases.find(className);
            return (result != _bases.end() ? (*result).second : nullptr);
        }

        const void* To(const std::string& className) const
        {
            if (_bases.size() == 0)
            {
                RegisterAllSubclasses();
            }

            auto result = _bases.find(className);
            return (result != _bases.end() ? (*result).second : nullptr);
        }

    protected:
        void RegisterSubclass(const void* ptr, const std::string& className) const
        {
            _bases[className] = const_cast<void*>(ptr);
        }

        virtual void RegisterAllSubclasses() const
        {
            RegisterSubclass(static_cast<const void*>(this), Object::GetClassName());
        }

    private:
        mutable std::map<std::string, void*> _bases;
};

////////////////////////////////////////////////////////////////////////////////
 
template <typename T>
T my_dynamic_cast(Object* ptr)
{
    return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
}

template <typename T>
T my_dynamic_cast(const Object* ptr)
{
    return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
}
 
////////////////////////////////////////////////////////////////////////////////
 
class InputStream : virtual public Object
{
    public:
        DEFINE_BASES(InputStream, Object);
        void Read() { }
};
 
class OutputStream : virtual public Object
{
    public:
        DEFINE_BASES(OutputStream, Object);
        void Write() { }
};
 
class IOStream : public InputStream, public OutputStream
{
    int _value;

    public:
        DEFINE_BASES(IOStream, InputStream, OutputStream);
        IOStream() : _value(0) { }

        int GetValue() const { return _value; }
        void SetValue(int value) { _value = value; }
};
 
int main()
{
    const Object*   co = new IOStream;
    const IOStream* cd = my_dynamic_cast<const IOStream*>(co);
    
    Object*   o = new IOStream;
    IOStream* d = my_dynamic_cast<IOStream*>(o);

    d->SetValue(42);
    
    printf("const:     %i, %p, %p\n", cd->GetValue(), co, cd);
    printf("non-const: %i, %p, %p\n", d->GetValue(), o, d);
    
    delete cd;
    delete d;

    return 0;
}

28 January 2013

Reimplementace dynamic_cast v C++

Článek uvede jednu z možností, jak efektivně nahradit funkcionalitu dynamic_cast v C++. Prezentovaný kód bude využívat nejnovější specifikace jazyka, C++11, ovšem s malým omezením a trochou snahy není problém kód přepsat pro C++03.

Přetypování bázové třídy na třídu odvozenou lze v C++ docílit dvěma způsoby - pomocí static_cast, pokud patříme k těm šťastnějším a přetypování je možné provést ještě v době kompilace, či pomocí dynamic_cast, kdy máme fakt pech a musíme sáhnout po RTTI a přetypování provést za běhu programu. Jedním z takových případů je pokus o přetypování z virtuální bázové třídy.

Zlé jazyky tvrdí, že potřeba dynamic_cast je známka špatného návrhu aplikace. Dovolím si lehce nesouhlasit a poukázat na existenci několika případů, kdy je dynamic_cast užitečný. Představte si, že pracujete s nějakou logovací funkcí, která má za úkol ukládat informace o jednotlivých událostech. Událost může mít svou bázovou třídu, řekněme Event, ze které dědí všechny typy událostí. Díky dynamic_cast můžeme o konkrétních událostech získat bližší informace - událost přetypujeme z bázové třídy Event na konkrétní třídu události, a poté z ní můžeme získat více informací.


V úvodu jsem psal o přetypování z virtuální bázové třídy na třídu odvozenou. Mnoho lidí se virtuální dědičnosti v C++ vyhýbá, ovšem může být užitečná v případě, kdy píšete nějaký framework bohatý na rozhraní. Osobně se mi v praxi osvědčilo dodržovat pravidlo, aby každé rozhraní (či abstraktní třída, chcete-li), které využívá vlastností jiného rozhraní, z něj dědilo virtuálně. Zároveň je dobrou praxí mít základní třídu pro všechny ostatní třídy, včetně rozhraní, např. Object. Toho mnoho známých projektů v C++ skutečně využívá.

Důvodem virtuální dědičnosti je zamezení vícenásobného vytvoření instance bázových tříd. Modelovou situací může být případ, kdy v projektu existují třídy ObjectInputStream, OutputStream a IOStream, který využívá vlastností dvou předchozích tříd, které zároveň dědí ze třídy Object. Pokud bychom nevyužili virtuální dědičnosti u InputStream a OutputStream, objekt IOStream by obsahoval dvě instance třídy Object. Pokud bychom se poté z objektu IOStream pokusili zavolat metodu GetHandle(), kompilátor by zahlásil chybu, jelikož by nevěděl, jakou ze dvou existujících metod zavolat. Díky virtuální dědičnosti existuje instance jen jedna, sdílená napříč všemi objekty uvnitř každé ze tříd. Tomuto případu se také říká diamond inheritance.

Příklad nevyužití virtuální dědičnosti


Příklad využití virtuální dědičnosti

Jak již bylo uvedeno, problém nastane ve chvíli, když bude potřeba přetypovat virtuální třídu na některou z odvozených tříd - Object na jakoukoliv jinou třídu - právě kvůli virtuální dědičnosti. Tento problém lze jednoduše vyřešit právě použitím dynamic_cast. Pro ty, kteří se dynamic_cast z jakéhokoliv důvodu štítí, uvedu alternativní způsob, jak chování dynamic_cast při splnění určitých pravidel reimplementovat.

Ukázka, jak by mohla v paměti vypadat vytvořená instance třídy IOStream - z obrázku je zřejmé, že neexistuje žádný primitivní způsob, jak Object přetypovat na nadtřídu.

Jedním z těchto pravidel právě je, že musí existovat základní bázová třída, ze které budou dědit všechny ostatní třídy, na které budeme chtít aplikovat dynamické přetypování. V našem případě třída Object. Účel této třídy bude zejména poskytnutí informací o odvozené třídě (její název) a dvojice metod To(const std::string&), které budou využity k přetypovávání na základě názvu třídy - jedna const a druhá non-const. Srdcem celého principu bude hash-tabulka uložená ve třídě Object, která má za úkol udržovat ukazatele na jednotlivé odvozené podtřídy na základě jejich názvů. Tabulka musí být označena klíčovým slovem mutable, abychom ji mohli editovat i z const metod.
class Object
{
    public:
        virtual ~Object();

        static const std::string& GetClassNameStatic();
        virtual const std::string& GetClassName() const;
    
        void* To(const std::string& className);
        const void* To(const std::string& className) const;

    private:
        mutable std::map<std::string, void*> _bases;
};
Tento samotný návrh samozřejmě není dostačující. Je potřeba zajistit metodu pro zaregistrování odvozené třídy a zvlášť metodu pro rekurzivní procházení celou hierarchií dědičnosti. Kód jsem rozdělil na dvě části z důvodu snazšího pochopení.
class Object
{
    public:
        virtual ~Object() { }

        static const std::string& GetClassNameStatic()
        {
            static std::string className("Object");
            return className;
        }

        virtual const std::string& GetClassName() const
        {
            return GetClassNameStatic();
        }
    
        void* To(const std::string& className)
        {
            if (_bases.size() == 0)
            {
                RegisterAllSubclasses();
            }

            auto result = _bases.find(className);
            return (result != _bases.end() ? (*result).second : nullptr);
        }

        const void* To(const std::string& className) const
        {
            if (_bases.size() == 0)
            {
                RegisterAllSubclasses();
            }

            auto result = _bases.find(className);
            return (result != _bases.end() ? (*result).second : nullptr);
        }

    protected:
        void RegisterSubclass(const void* ptr, const std::string& className) const
        {
            _bases[className] = const_cast<void*>(ptr);
        }

        virtual void RegisterAllSubclasses() const
        {
            RegisterSubclass(static_cast<const void*>(this), Object::GetClassName());
        }

    private:
        mutable std::map<std::string, void*> _bases;
};
Na první pohled je zřejmé, jaký bude princip. Hierarchie dědičnosti se nevytvoří do té doby, dokud nebude zavolána metoda To(), z čehož plyne výhoda, že tabulka nebude vytvořena do té doby, dokud to nebude potřeba. Použití konstrukce if (_bases.size() == 0) je bezpečné, jelikož v tabulce je vždy minimálně přítomen sám Object.

Pro donucení odvozené třídy k registraci sebe sama a svých předků, využijeme překrytí metod RegisterAllSubclasses() a GetClassName() současně s novou definicí statické metody GetClassNameStatic(). Význam vytvoření nové definice této statické metody bude vysvětlen později. Třída InputStream by pak mohla vypadat nějak takto:
class InputStream : virtual public Object
{
    public:
        static const std::string& GetClassNameStatic()
        {
            static std::string className("InputStream");
            return className;
        }

        virtual const std::string& GetClassName() const override
        {
            return GetClassNameStatic();
        }

        void Read();

    protected:
        virtual void RegisterAllSubclasses() const override
        {
            RegisterSubclass(static_cast<const void*>(this), InputStream::GetClassName());
            Object::RegisterAllSubclasses();
        }
};
V metodě RegisterAllSubclasses() je u volaných metod důležité uvádět konkrétní názvy tříd. V případě, kdy by nebyly uvedeny, by se zavolaly metody překryté nejvíce derivovanou třídou (kdyby ze třídy InputStream dědil IOStream, metoda GetClassName() by vždy vracela název třídy IOStream). Poté zavoláme metodu RegisterAllSubclasses() na všech předcích, které opět rekurzivně zaregistrují své předky. Metoda RegisterAllSubclasses() by ve třídě IOStream vypadala následovně:
        virtual void RegisterAllSubclasses() const override
        {
            RegisterSubclass(static_cast<const void*>(this), IOStream::GetClassName());
            InputStream::RegisterAllSubclasses();
            OutputStream::RegisterAllSubclasses();
        }
Opakovaný zápis těchto metod v každé třídě zvlášť není samozřejmě pohodlný, proto je výhodnější přenechat tuto práci makru. Makro bude přebírat název aktuální třídy a za ním bude následovat seznam všech předků (variadic macro). Samotné registrování předků bude využívat malého triku s variadic templates, které C++11 zavedlo.
#define DEFINE_BASES(class, ...)                                                \
    static const std::string& GetClassNameStatic()                              \
    {                                                                           \
        static std::string className(#class);                                   \
        return className;                                                       \
    }                                                                           \
                                                                                \
    const std::string& GetClassName() const override                            \
    {                                                                           \
        return GetClassNameStatic();                                            \
    }                                                                           \
                                                                                \
    template <typename _empty>                                                  \
    void RegisterAllSubclasses() const                                          \
    {                                                                           \
                                                                                \
    }                                                                           \
                                                                                \
    template <typename _empty, typename T, typename... Args>                    \
    void RegisterAllSubclasses() const                                          \
    {                                                                           \
        T::RegisterAllSubclasses();                                             \
        RegisterAllSubclasses<void, Args...>();                                 \
    }                                                                           \
                                                                                \
    virtual void RegisterAllSubclasses() const override                         \
    {                                                                           \
        RegisterSubclass(static_cast<const void*>(this), class::GetClassName());\
        RegisterAllSubclasses<void, __VA_ARGS__>();                             \
    }
Princip je jednoduchý - bázové třídy se budou rekurzivně registrovat. Až se všechny zaregistrují a parametr Args bude prázdný, rekurze se ukončí voláním "prázdné" metody template <typename _empty> void RegisterAllSubclasses(). V případě výše uvedeného případu s třídou IOStream bude průběh volání následující:


Nakonec zbývá jediná věc - samotná funkce pro dynamické přetypování. Nyní přichází na řadu výhoda definované statické metody pro zjištění názvu třídy. Funkce totiž požádá o název třídy předané přes šablonu právě skrze statickou funkci GetClassNameStatic() a předá ji metodě To(const std::string&). Ta se v hash-tabulce pokusí najít ukazatel na konkrétní podtřídu, kterou pokud najde, vrátí ji.
template <typename T>
T my_dynamic_cast(Object* ptr)
{
    return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
}

template <typename T>
T my_dynamic_cast(const Object* ptr)
{
    return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
}
std::remove_pointer<T> někteří znají z knihovny Boost, v C++11 je ale součástí standardní knihovny ve hlavičkovém souboru type_traits. Důvod, proč se ve funkci nachází, je zřejmý - funkce potřebuje získat původní datový typ třídy, zatímco samotné funkci je předáván pouze ukazatel na ni.

Na závěr dodám, že návrhů na rozšíření je mnoho. Mimo urychlení funkcionality zaměněním indexování na základě samotného hashe textového řetězce (díky čemuž je tato alternativa až 10x rychlejší než standardní dynamic_cast) lze tuto kostru projektu rozšířit na plnohodnotné zavedení vlastního RTTI do projektu.

Nyní už jen samotný zdrojový kód:
#include <iostream>
#include <string>
#include <map>
#include <type_traits>

#define DEFINE_BASES(class, ...)                                                \
    static const std::string& GetClassNameStatic()                              \
    {                                                                           \
        static std::string className(#class);                                   \
        return className;                                                       \
    }                                                                           \
                                                                                \
    const std::string& GetClassName() const override                            \
    {                                                                           \
        return GetClassNameStatic();                                            \
    }                                                                           \
                                                                                \
    template <typename _empty>                                                  \
    void RegisterAllSubclasses() const                                          \
    {                                                                           \
                                                                                \
    }                                                                           \
                                                                                \
    template <typename _empty, typename T, typename... Args>                    \
    void RegisterAllSubclasses() const                                          \
    {                                                                           \
        T::RegisterAllSubclasses();                                             \
        RegisterAllSubclasses<void, Args...>();                                 \
    }                                                                           \
                                                                                \
    virtual void RegisterAllSubclasses() const override                         \
    {                                                                           \
        RegisterSubclass(static_cast<const void*>(this), class::GetClassName());\
        RegisterAllSubclasses<void, __VA_ARGS__>();                             \
    }

class Object
{
    public:
        virtual ~Object() { }

        static std::string& GetClassNameStatic()
        {
            static std::string className("Object");
            return className;
        }

        virtual const std::string& GetClassName() const
        {
            return GetClassNameStatic();
        }

        void* To(const std::string& className) 
        {
            if (_bases.size() == 0)
            {
                RegisterAllSubclasses();
            }

            auto result = _bases.find(className);
            return (result != _bases.end() ? (*result).second : nullptr);
        }

        const void* To(const std::string& className) const
        {
            if (_bases.size() == 0)
            {
                RegisterAllSubclasses();
            }

            auto result = _bases.find(className);
            return (result != _bases.end() ? (*result).second : nullptr);
        }

    protected:
        void RegisterSubclass(const void* ptr, const std::string& className) const
        {
            _bases[className] = const_cast<void*>(ptr);
        }

        virtual void RegisterAllSubclasses() const
        {
            RegisterSubclass(static_cast<const void*>(this), Object::GetClassName());
        }

    private:
        mutable std::map<std::string, void*> _bases;
};

////////////////////////////////////////////////////////////////////////////////
 
template <typename T>
T my_dynamic_cast(Object* ptr)
{
    return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
}

template <typename T>
T my_dynamic_cast(const Object* ptr)
{
    return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
}
 
////////////////////////////////////////////////////////////////////////////////
 
class InputStream : virtual public Object
{
    public:
        DEFINE_BASES(InputStream, Object);
        void Read() { }
};
 
class OutputStream : virtual public Object
{
    public:
        DEFINE_BASES(OutputStream, Object);
        void Write() { }
};
 
class IOStream : public InputStream, public OutputStream
{
    int _value;

    public:
        DEFINE_BASES(IOStream, InputStream, OutputStream);
        IOStream() : _value(0) { }

        int GetValue() const { return _value; }
        void SetValue(int value) { _value = value; }
};
 
int main()
{
    const Object*   co = new IOStream;
    const IOStream* cd = my_dynamic_cast<const IOStream*>(co);
    
    Object*   o = new IOStream;
    IOStream* d = my_dynamic_cast<IOStream*>(o);

    d->SetValue(42);
    
    printf("const:     %i, %p, %p\n", cd->GetValue(), co, cd);
    printf("non-const: %i, %p, %p\n", d->GetValue(), o, d);
    
    delete cd;
    delete d;

    return 0;
}