Прямое объявление, unique_ptr и инициализатор в классе

я прочитал Является ли std :: unique_ptr<T> Требуется знать полное определение Т? а также Переслать объявление с unique_ptr?, но мой вопрос более конкретный.

Следующие компиляции:

// Compile with $ g++ -std=c++11 -c <filename>
#include <memory>
class A; // fwd declaration

class AUser
{
AUser();  // defined elsewhere
~AUser(); // defined elsewhere
std::unique_ptr<A> m_a;
};

Следующее не делает:

// Compile with $ g++ -std=c++11 -c <filename>
#include <memory>
class A; // fwd declaration

class AUser
{
AUser();  // defined elsewhere
~AUser(); // defined elsewhere
std::unique_ptr<A> m_a{nullptr};
};

Ошибка

$ g++ -std=c++11 -c fwd_decl_u_ptr.cpp
In file included from /usr/include/c++/4.7/memory:86:0,
from fwd_decl_u_ptr.cpp:3:
/usr/include/c++/4.7/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = A]’:
/usr/include/c++/4.7/bits/unique_ptr.h:173:4:   required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = A; _Dp = std::default_delete<A>]’
fwd_decl_u_ptr.cpp:9:33:   required from here
/usr/include/c++/4.7/bits/unique_ptr.h:63:14: error: invalid application of ‘sizeof’ to incomplete type ‘A’

РЕДАКТИРОВАТЬ:
Насколько я понимаю, здесь происходит то, что инициализатор в классе подразумевает способность инициализировать unique_ptr<A> уже в момент объявления AUser, Так как тип unique_ptr<A> на самом деле unique_ptr<A, default_delete<A>>возможность инициализации подразумевает возможность инициализации default_delete<A>, И для этого A должен быть полностью определен.

Слабым звеном в этом рассуждении является предположение, что инициализатор в классе подразумевает возможность инициализации соответствующего члена данных в момент объявления класса! Это кажется интуитивно понятным, поскольку инициализатор является частью декларации. Но мне было бы удобнее, если бы я нашел что-то в стандарте, явно указав это. В противном случае я все еще могу думать о решениях для реализации, которые бы не требовали этого. Например, компилятор может просто взять выражение инициализатора и применить его только в конструкторах, где инициализация атрибута не была задана явно.

Итак, может ли кто-нибудь отослать меня к стандартному разделу / отрывку, который подразумевает необходимость полного определения A во втором случае? Я не нашел много о инициализаторах в классе в стандарте (только нашел, что их называют «скобки или равно-инициализаторы не статично
данные членов «), но с этим ничего не связано.

5

Решение

Во втором случае генерируется деструктор по умолчанию [неверный] в месте AUser определение [/ Неправильно] (в этом случае это фактически делается после обработки всего кода). Так же, как определение конструктора внутри AUser сделал бы.

Тем не менее, в любом случае вам нужно дать определение A в том же модуле компиляции. Так может просто что-то подобное удовлетворит тебя?

#include <memory>

class A;

class AUser
{
std::unique_ptr<A> m_a;
AUser();
};class A
{
// ...
};AUser::AUser()
: m_a(nullptr)
{ }
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]