Как переслать объявление класса для использования в стандартном контейнере 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 знать полное определение T?

Другие вопросы по тегам