Как переслать объявление класса для использования в стандартном контейнере unique_ptr
Можно ли избежать отображения полного определения класса при использовании его в стандартном контейнере интеллектуальных указателей? Например, я не могу получить следующее для компиляции:
#include <memory>
#include <map>
class Foo;
class Bar {
public:
Bar();
std::map<int, std::unique_ptr<Foo>> myMap;
};
Компилятор Clang, похоже, настаивает на полном определении Foo
доступно при компиляции Bar
, Есть ли техника, которую я мог бы использовать, чтобы избежать включения Foo.h?
Edit1:
ошибка: недопустимое применение sizeof к неполному типу Foo: static_assert(sizeof(_Tp) > 0, "default_delete не может удалить неполный тип");
Edit2: Нет, это не дубликат, это std::unique_ptr, необходимый для того, чтобы знать полное определение. Просто использование unique_ptr не обязательно требует полного определения, но использование его внутри стандартного контейнера вводит дополнительные складки.
Edit3: Оказывается, я могу достичь (почти) того, что я хочу, введя базовый класс с виртуальным деструктором. Тогда класс, имеющий контейнер умных указателей на базовый класс, скомпилирует без проблем. Больше ничего не должно присутствовать в базовом классе, а базовый класс должен быть полностью видимым. Таким образом, все сложности производных классов могут быть скрыты при компиляции контейнера.
2 ответа
Даже если строгое прямое объявление не скомпилирует контейнер интеллектуальных указателей, все же возможно решить большинство практических задач и избежать раскрытия полного класса при определении пользовательского класса с контейнером. Просто представьте базовый класс с общедоступным виртуальным отвлечением и сделайте его видимым.
в fooBase.h
class FooBase {
public virtual ~FooBase();
};
в бар.ч
#include "foobase.h"
#include <memory>
#include <map>
class Bar {
...
std::map<int, std::unique_ptr<FooBase>> myMap;
}
Когда Foo получен из FooBase и помещен в его собственный заголовочный файл, изменения в Foo больше не требуют перекомпиляции Bar.
Вы должны сделать деструктор и конструкторы Foo публичными. Если у вас возникли другие ошибки, пожалуйста, опубликуйте их, так как это трудно сказать по вашему первоначальному сообщению. Следующий код компилируется:
#include <memory>
#include <map>
class Foo;
class Bar {
public:
Bar () {};
std::map<int, std::unique_ptr<Foo> > myMap;
};
class Foo {
public:
Foo () {};
~Foo () {};
};
int main ()
{
Bar b;
}
РЕДАКТИРОВАТЬ: проверить эти другие сообщения: Переслать объявление с unique_ptr?
Требуется ли std::unique_ptr