2013-03-04 2 views
3

У меня есть эта договоренность:C++ unique_ptr против друга класса частных деструктор

class LexedFile 
    { 
    friend class Lex; 
//... 
private: 
    ~LexedFile(); 
    }; 

class Lex 
    { 
//... 
private: 
    std::map<std::string, std::unique_ptr<LexedFile> > Files; 
    }; 

Lex является единственным создателем LexedFile объектов и сохраняет право собственности на все LexedFile объектов, которые она создает на карте. К сожалению, компилятор жалуется на это из-за правил видимости от переменной карты до деструктора LexedFile. Я могу исправить эту проблему, сделав ~LexedFile() общедоступной, но, конечно, причина, по которой я сделал это частным, - это усилить решение о том, что объекты этого типа принадлежат только объектам Lex.

Мой вопрос: каковы мои переносные варианты для создания unique_ptr счастливые и сохраняющие ~LexedFile() приватные? По-моему, он, по-видимому, должен работать с последними версиями g ++ и последними версиями Visual C++.

я принял удар на вставляя что-то вроде:

friend class std::unique_ptr<LexedFile>; 

, но даже если он работал (это не так) это своего рода казалось, опираясь на предположения о реализации, которые не могут быть портативными.

+0

передать свой собственный Deleter вместо использования по умолчанию один :) –

+0

'друг класс станд :: default_delete ' может также, возможно, работать, в зависимости от реализации, но я бы не стал рассчитывать на нем, и он также, вероятно, раскрывает ваш деструктор больше, чем вы хотели бы его обнажить. –

+0

Или даже лучше 'friend std :: unique_ptr :: deleter_type;' который также будет работать для 'std :: unique_ptr', который использует пользовательский Deleter. –

ответ

4

Просто создайте экземпляр std::unique_ptr со своим собственным дебетером. Я думаю, что это будет работать:

class LexedFile 
{ 
    friend class Lex; 

//... 
private: 
    struct Deleter 
    { 
     void operator()(LexedFile *file) const 
     { 
      delete file; 
     } 
    }; 

    ~LexedFile(); 
}; 

class Lex 
{ 
//... 
private: 
    std::map<std::string, std::unique_ptr<LexedFile, LexedFile::Deleter>> Files; 
}; 
+0

Спасибо за вашу помощь! Подождав загрузки (почти) стандарта и суеты, я решил пойти с объявлением вашего друга. Казалось, что он должен быть переносимым (после смены класса на «struct»), и альтернатива создания обертки просто для борьбы с разрешениями была удручающей. :-) Какие бы дыры он ни имел, он определенно по-прежнему запрещает любому, кто прямо вызывает удаление этого класса, что является основным напоминанием, которое я хотел бы работать. Еще раз спасибо! –

+0

нормально, не проблема, удачи –

+0

@RonBurk Я почти уверен, что вы полагаетесь на неопределенное поведение, между прочим, пока вы в порядке с этим. –

Смежные вопросы