Создание shared_ptr класса, содержащего unique_ptr для перенаправленного типа, завершается неудачно - PullRequest
0 голосов
/ 04 октября 2018

Этот код

#include <memory>

class A {
public:
  class B;
  std::unique_ptr<B> b;
  A();
};

void foo() {
  std::make_shared<A>();
}

Сбой:

In file included from /usr/include/c++/7/memory:80:0,
                 from aaa.cpp:1:
/usr/include/c++/7/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = A::B]’:
/usr/include/c++/7/bits/unique_ptr.h:268:17:   required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = A::B; _Dp = std::default_delete<A::B>]’
aaa.cpp:3:7:   required from ‘void __gnu_cxx::new_allocator<_Tp>::destroy(_Up*) [with _Up = A; _Tp = A]’
/usr/include/c++/7/bits/alloc_traits.h:487:4:   required from ‘static void std::allocator_traits<std::allocator<_Tp1> >::destroy(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*) [with _Up = A; _Tp = A; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<A>]’
/usr/include/c++/7/bits/shared_ptr_base.h:535:35:   required from ‘void std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_M_dispose() [with _Tp = A; _Alloc = std::allocator<A>; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2]’
aaa.cpp:12:1:   required from here
/usr/include/c++/7/bits/unique_ptr.h:76:22: error: invalid application of ‘sizeof’ to incomplete type ‘A::B’
  static_assert(sizeof(_Tp)>0,

Кажется, компилятор пытается определить удаление по умолчанию для типа A::B, который объявлен в прямом направлении.

Может кто-нибудь объяснить, почему make_shared нужно знать удаление по умолчанию?И как это побороть?

1 Ответ

0 голосов
/ 04 октября 2018

По той же причине delete не работает с неполными типами, shared_ptr тоже не работает.

Решение заключается в предоставлении пользовательской функции распределителя:

#include <memory>

class A {
public:
  class B;
  std::unique_ptr<B> b;
  A();
};
std::shared_ptr<A> AMakeShared();

void foo() {
  AMakeShared();
}

Определениефункции AMakeShared должен быть в переводческой единице, где определение A::B не является неполным.Предположим, еще один файл file.cpp, содержащий:

class A::B {
}

std::shared_ptr<A> AMakeShared() {
    return std::make_shared<A>();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...