C++: прямое объявление класса с помощью удаления для уникального указателя, который можно повторить

В C++ можно использовать предварительное объявление, чтобы разрешить указатели на неполный тип.

class A;
A *p;

Однако в некоторых случаях я хочу вместо этого объявить уникальный указатель, поэтому я использую

class A;
class A_Deleter { void operator()(A*); }
unique_ptr<A, A_Deleter> p;

Этого достаточно во многих случаях, но есть один существенный недостаток. В отличие от настоящего предварительного объявления, его нельзя написать дважды. т.е. пока этот код компилируется:

class A;
class A;

Этот не:

class A;
class A_Deleter { void operator()(A*); }
class A;
class A_Deleter { void operator()(A*); }

Как бы вы объявили удаляемый класс?


person tohava    schedule 17.02.2015    source источник


Ответы (3)


Зачем вам это повторять?

Поместите объявления в заголовок (с надлежащими охранниками включения) и включите их там, где это необходимо.

person Jonathan Wakely    schedule 17.02.2015

Что вы можете сделать, так это создать заголовок специально для прямого объявления, которое также объявляет средство удаления. Дайте заголовку обычные охранники и включите этот заголовок вместо прямого объявления A.

Но вообще я бы пошел другим путем. Если мне просто нужно объявить уникальный указатель, я бы просто объявил вперед и сделал unique_ptr<A>. Если бы у меня действительно был контекст, в котором уникальный указатель уничтожался, я бы взял полное определение A.

person Sebastian Redl    schedule 17.02.2015
comment
Я хочу иметь возможность удалить A без доступа к его полному определению, только для удаления. Кроме того, хотя заголовок и является решением, он вынуждает меня иметь очень короткие заголовки, которые определяют предварительное объявление только для одного класса, что имхо запутанно. - person tohava; 17.02.2015
comment
Грязный или не компилируется. Выбери один. - person Jonathan Wakely; 17.02.2015
comment
@tohava Я не думаю, что это так грязно. Я действительно делаю это в своих проектах. Это очень хорошо показывает класс в перспективе — расположение заголовка говорит вам кое-что о том, откуда взялся класс. И если позже вы обнаружите, что вам нужно заменить class A; на typedef SomethingOrOther A;, у вас будет гораздо меньше проблем, когда это будет в заголовке. - person Angew is no longer proud of SO; 17.02.2015
comment
@Angew - Хорошее замечание по поводу typedefs. Если у меня есть несколько очень маленьких связанных классов, я обычно помещаю их в один и тот же заголовок, я думаю, это проясняет ситуацию, а не помещает каждый в отдельный заголовок в стиле java. Хотя, наверное, я решу это по-вашему. - person tohava; 17.02.2015

Я думаю, что нашел свое решение.

Я определяю класс, видимый через заголовок для всех:

template <class T> class deleter { void operator()(T *x); }; 

Затем я могу избавиться от необходимости объявлять класс удаления и писать такие вещи:

class A;
unique_ptr<A, deleter<A> > p;

deleter<T>::operator() для каждого T можно реализовать с помощью специализации в собственном файле .cpp.

person tohava    schedule 17.02.2015