Подтвердить что ты не робот

Как определить, имеет ли класс С++ vtable?

Мой друг прислал мне следующий вызов сегодня утром:

Учитывая следующий код, предложите реализацию OBJECT_HAS_VTABLE чтобы программа OBJECT_HAS_VTABLE AnObject has a vtable = 0, AnObjectWithVTable has a vtable = 1.

class AnObject
{
    int m_a;
    void DoSomething() {}

public: 
    AnObject() {m_a = 0;}
};

class AnObjectWithVTable
{
    int m_b;
    virtual void DoStuff() { }

public: 
    AnObjectWithVTable() {m_b = 0;}
};

void main()
{
    printf("AnObject has a vtable = %i, AnObjectWithVTable has a vtable = %i\n",
           OBJECT_HAS_VTABLE(AnObject),
           OBJECT_HAS_VTABLE(AnObjectWithVTable));
}

Я пришел к следующему решению, которое я считаю достаточно приличным:

template <typename T>
bool objectHasVtable()
{
    class __derived : public T {};
    T t;
    __derived d;

    void *vptrT=*((void **)&t);
    void *vptrDerived=*((void **)&d);

    return vptrT != vptrDerived;
}

#define OBJECT_HAS_VTABLE(T) objectHasVtable<T>()

Есть ли лучшее решение этой проблемы?

редактировать

Решение не должно быть общим для всех компиляторов. Он может работать на gcc, g++, MSVC... Просто укажите, для какого компилятора известно, что ваше решение действительно. Мой для MSVC 2010.

4b9b3361

Ответ 1

Стандартный метод заключается в использовании std::is_polymorphic из С++ 11/С++ 03 TR1/Boost, чтобы определить, содержат ли класс (и его базы) какие-либо виртуальные члены.

#include <type_traits>
#define OBJECT_HAS_VTABLE(T) (std::is_polymorphic<T>::value)

Ответ 2

За полноту, вот ответ, который мой приятель просто послал мне. По внешнему виду это, вероятно, похоже на то, как TR1 это делает (хотя я сам не смотрел на код).

template<class T>
class HasVTable
{
public :
    class _Derived_ : public T
    {
        virtual void _force_the_vtable(){}
    }
    enum { Value = (sizeof(T) == sizeof(Derived)) };
};

#define OBJECT_HAS_VTABLE(type) HasVTable<type>::Value