У меня есть некоторые странные проблемы при реализации интрузивного контейнера на C++. Учитывая следующий упрощенный код:Ошибка использования абстрактного типа в шаблоне C++
struct IFace {
virtual int foo() const = 0;
};
struct Impl : public IFace {
int foo() const { return 111; }
};
template <typename T> struct IntrusiveHook {
T item;
IntrusiveHook<T>* next;
};
template <typename T> struct IntrusiveList {
IntrusiveList() : head(0), tail(0) {}
template <typename U>
void add(IntrusiveHook<U>& addItem) {
if (0 == head) {
head = reinterpret_cast<IntrusiveHook<T>*>(&addItem);
tail = head;
}
else {
tail->next = reinterpret_cast<IntrusiveHook<T>*>(&addItem);
tail = tail->next;
}
}
IntrusiveHook<T>* head;
IntrusiveHook<T>* tail;
};
void testList() {
IntrusiveHook<Impl> impl;
IntrusiveList<IFace> list;
list.add(impl);
// list.head->item.foo();
}
Я получаю следующее сообщение об ошибке - для «добавить» -Call (если закомментировать строку list.head->item.foo()
, как указано выше):
error C2259: 'IFace' : cannot instantiate abstract class
due to following members:
'int IFace::foo(void) const' : is abstract
testwas.cpp(7) : see declaration of 'IFace::foo'
testwas.cpp(25) : see reference to class template instantiation 'IntrusiveHook<T>' being compiled
with
[
T=IFace
]
testwas.cpp(41) : see reference to function template instantiation 'void IntrusiveList<T>::add<Impl>(IntrusiveHook<Impl> &)' being compiled
with
[
T=IFace
]
Когда комментирует в line list.head->item.foo()
Я получаю другую ошибку компиляции, предыдущая была оставлена (это странное поведение и происходит как на компиляторах VC++, так и на gcc)
Проблемный вызов кажется tail->next = ...
или e особенно оператор ->
на абстрактный тип, используемый здесь.
So: Как исправить эту проблему?
- добавить реализацию по умолчанию Ф.О.
foo
вIFace
- который не то, что я хочу, но это устраняет проблему вид Hacky решение: переписать в
tail->next
вreinterpret_cast<IntrusiveHook<U>*>(tail)->next = &addItem;
tail = reinterpret_cast<IntrusiveHook<T>*>(reinterpret_cast<IntrusiveHook<U>*>(tail)->next);
- но он не работает с VC++ (2010), но с gcc... или выполняя другие уродливые слепки
Но ПОЧЕМУ это проблема в первую очередь? Обычно не должно быть проблем с доступом к типу указателя с оператором «->».
Любая помощь будет оценена по достоинству. Благодаря!
Edit:
Просто для удобства я хотел бы иметь IntrusiveHook уже содержат элемент в качестве экземпляра. Это также трюк с интрузивным - когда я получил это право - просто добавить функциональность указателя к элементу без изменения самого элемента. «новый» не является вариантом, так как код должен работать во встроенной среде без new
.
Также, конечно, я хотел бы использовать список с абстрактными элементами, потому что класс использования не знал бы классов реализации.
IntrusiveList лист; list.add (impl); –
или 'IntrusiveList list; list.add (new Impl()); 'так же, как ошибка говорит: вы не можете создавать объекты абстрактного класса. Ваш IntrusiveList не может работать с 'IFace', потому что это не полный тип, но он может работать с' IFace * '(потому что для объявления указателя вам не нужно знать полный тип) –
user463035818