Хорошо известное решение, позволяющее избежать медлительности dynamic_cast?

Мне нужен был полиморфизм времени выполнения, поэтому я использовал.dynamic_cast

Но теперь у меня было две проблемы -dynamic_cast былоочень медленно! (Прокрутите вниз для сравнения.)

Короче говоря, я решил проблему таким образом, используя:static_cast

struct Base
{
    virtual ~Base() { }
    virtual int type_id() const = 0;

    template
    T *as()
    { return this->type_id() == T::ID ? static_cast(this) : 0; }

    template
    T const *as() const
    { return this->type_id() == T::ID ? static_cast(this) : 0; }
};

struct Derived : public Base
{
    enum { ID = __COUNTER__ };  // warning: can cause ABI incompatibility
    int type_id() const { return ID; }
};

int main()
{
    Base const &value = Derived();
    Derived const *p = value.as();  // "static" dynamic_cast
}

Но я'Я, конечно, не первый, кто столкнулся с этой проблемой, поэтому я подумал, что стоит спросить:

Вместо того, чтобы придумывать подобное решение, выпеченное в домашних условиях, есть ли хорошо известный шаблон / библиотека, которую я могу использовать для решения этой проблемы в будущем?

Образец теста

Чтобы почувствовать то, что яя говорю, попробуйте код ниже -dynamic_cast был примерно15раз медленнее, чем простоvirtual Позвоните на мою машину (110 мс против 1620 мс с кодом ниже):

#include 
#include 

struct Base { virtual unsigned vcalc(unsigned i) const { return i * i + 1; } };
struct Derived1 : public Base 
{ unsigned vcalc(unsigned i) const { return i * i + 2; } };
struct Derived2 : public Derived1
{ unsigned vcalc(unsigned i) const { return i * i + 3; } };

int main()
{
    Base const &foo = Derived2();
    size_t const COUNT = 50000000;
    {
        clock_t start = clock();
        unsigned n = 0;
        for (size_t i = 0; i < COUNT; i++)
            n = foo.vcalc(n);
        printf("virtual call: %d ms (result: %u)\n",
            (int)((clock() - start) * 1000 / CLOCKS_PER_SEC), n);
        fflush(stdout);
    }
    {
        clock_t start = clock();
        unsigned n = 0;
        for (size_t i = 0; i < COUNT; i++)
            n = dynamic_cast(foo).vcalc(n);
        printf("virtual call after dynamic_cast: %d ms (result: %u)\n",
            (int)((clock() - start) * 1000 / CLOCKS_PER_SEC), n);
        fflush(stdout);
    }
    return 0;
}

Когда я просто удаляю словоvirtual и изменитьdynamic_cast вstatic_castЯ получаю 79мс времени выполнения - поэтому виртуальный вызов медленнее, чем статический, на ~ 25%!

Ответы на вопрос(2)

Ваш ответ на вопрос