2015-04-01 2 views
1

У меня есть тип, который наследуется от определенного шаблоном типа. Определенный тип шаблона гарантированно имеет заданный базовый класс. Я хочу, чтобы иметь возможность dynamic_cast или иначе находить типы в контейнере, которые соответствуют моему производному типу, независимо от параметра шаблона.dynamic_cast Класс шаблона с «известным» наследованием

// A bunch of classes exist which inherit from Base already. 
class Base{}; 
class Base2 : public Base {}; 
class BaseN : public Base {}; 

// Some new classes can inherit from any Base-derived class, 
// but also have special attributes (i.e. function "f"). 
template<typename T = Base> 
class Derived : public T 
{ 
    static_assert(std::is_base_of<Base, T>::value, 
     "Class must inherit from a type derived from Base.") 

    public: 
     void f(); 
}; 

// 
// Now process a collection of Base pointers. 
// 

std::vector<Base*> objects; 

// The vector may contain classes that are not "Derived". 
// I only care about the ones that are. 
// I want the cast here to return non-null for Derived<Base>, 
// Derived<Base2>, Derived<BaseN>, but null for Base, Base2, etc. 

// This will be Null, Good. 
objects.push_back(new Base) 
auto dcast0 = dynamic_cast<Derived<Base>*>(objects[0]); 

// This will be Non Null, Good. 
objects.push_back(new Derived<Base>); 
auto dcast1 = dynamic_cast<Derived<Base>*>(objects[1]); 

// This will be Null, BAD! HELP! 
objects.push_back(new Derived<Base2>); 
auto dcast2 = dynamic_cast<Derived<Base>*>(objects[2]); 
+3

Производные ! = Производные . Они полностью разные, поэтому dcast2 правильно установлен в null. Один из способов обойти это состоит в том, чтобы заставить Derived наследовать от другого класса, скажем DerivedBase, а затем динамический приведение к этому. – Creris

+0

Вы смешиваете два разных понятия вместе: полиморфизм времени выполнения и полиморфизм времени компиляции. Вы могли бы пойти, как предложил Creris или рассмотреть возможность реорганизации вашего кода, чтобы избежать сравнения разных типов шаблонов. –

+0

. Производные и Derived НЕ являются совершенно разными типами, поскольку оба они в конечном счете наследуют от Base. То есть, я мог бы применить любой из них к базе * успешно. Я не утверждаю, что броски были неправильными, только иллюстрируя то, что я хотел от некоторого возможного решения. Действительно, это было смешение гарантии времени компиляции, которая наследуется от Base, и обе имеют тот же интерфейс, определенный Derived, который мне бы хотелось использовать во время выполнения. Использование предлагаемого DerivedBase - это простое решение, которое в конечном итоге учитывает 90% того, что я хотел. – DiB

ответ

1

Как было предложено Creris' в комментариях, вам нужно, не шаблонный базовый класс, который является общим для всех ваших Derived<> шаблонных классов. Кроме того, наследование до Base должно быть виртуальным, так что существует только один экземпляр Base, когда создается экземпляр Derived<>.

struct Base { virtual ~Base() {} }; 
struct Base2 : virtual Base {}; 

struct DerivedBase : virtual Base {}; 

template <typename BASE = Base> 
struct Derived : DerivedBase, BASE {}; 

    Base *b = new Derived<Base2>; 
    assert(dynamic_cast<DerivedBase *>(b)); 
+0

Я надеялся, что у кого-то есть какое-то вуду, но вернемся к основам, чтобы все перевести. Цените проверку здравомыслия! – DiB