2012-03-28 2 views
1

У меня был шаблон в течение некоторого времени, в который обертываются библиотеки C FILE *. Это довольно классическая реализация общего указателя на класс оболочки для FILE *. Причиной использования моего собственного пользовательского общего указателя является предоставление бесплатных функций для некоторых функций библиотеки FILE FILE *, чтобы позволить мне выполнить замену устаревшего кода, который работает с FILE *.Нужна помощь в разрешении полиморфизма времени выполнения с использованием шаблонов

Реализация, которая у меня есть, использует внутреннюю оболочку, которая гарантирует, что при ее удалении принадлежащий ФАЙЛ * закрыт. RAII.

Однако я пришел к необходимости создания подобной системы для обработки случая, когда я хочу, чтобы базовый ФАЙЛ * был сброшен & усечен, а не закрыт, когда уничтожен последний держатель FILE *. Другими словами, у меня есть открытый FILE * исходного типа гарантированного закрытия, но вы хотите передать неопубликованную копию FILE * другому объекту, который будет гарантировать, что когда последний экземпляр будет уничтожен, это он будет очищаться от &, а не закрывать его, а затем оставлять меня с базовым файлом * в открытом состоянии, но с содержимым потока, сброшенного на диск (и размером файла, отражающим только действительное содержимое).

Я решил это тривиально для полиморфизма времени компиляции. Но мне нужно каким-то образом предоставить полиморфизм во время выполнения, и я действительно не хочу ставить еще один-слой-косвенный подход к этому сценарию (т. Е. Если я использовал полиморфный указатель на автозавершение или авто-флеш FILE * wrapper, я был бы золотым, но я действительно хочу сохранить ту же самую глубину, что и сейчас, и скрыть полиморфизм внутри реализации пользовательского общего указателя).

В принципе, если у меня есть:

template <class WrapperT> 
class FilePointerT 
{ 
public: 
    // omitted: create, destroy, manipulate the underlying wrappered FILE* 
private: 
    WrapperT * m_pFileWrapper; 
    ReferenceCount m_rc; 
} 

Очевидно, тонны деталей опущено. Достаточно сказать, что когда последний из этих объектов удаляется, он удаляет последний m_pFileWrapper (на самом деле, если бы я переписывал этот код, я бы, вероятно, использовал boost :: shared_ptr).

Несмотря на это, реальная проблема здесь я озадачен о том, как иметь FilePointerT <WrapperT> которого WrapperT может меняться, но может быть использован в коде, как если бы они были все-таки (что, в конце концов, они , так как реализация WrapperT имеет нулевое влияние на структуру и интерфейс FilePointerT (по существу Pimpl).

что я могу заявить, что может возможно провести любой FilePointerT <WrapperT> для любого WrapperT?

Или, как могу ли я изменить определение FilePointerT, чтобы я мог предоставить конкретный WrapperT?

ответ

0

Для чего важно, чтобы я включил оболочку в класс FilePointer вместо того, чтобы сделать ее частью своего типа.

class FilePointer 
{ 
public: 
    // create using a file wrapper (which will handle policy issues) 
    FilePointer(FileWrapper * pfw) : m_pFileWrapper(pfw) { } 

protected: 
    FileWrapper * m_pFileWrapper; // wrapper has close/flush policy 
    ReferenceCount m_references; // reference count 
}; 

Затем файл указатель просто делегирует реальную работу обертки, и обертка реализует необходимую политику, и код может быть написан потреблять FilePointer (ы).

Есть, очевидно, другие способы сделать это, но с этим я и пошел.

3

Не можете ли вы просто использовать std::shared_ptr<FILE *, deleter_function>? Предоставляйте обычные перегрузки для бесплатных функций, без смешного шаблона malarky.

+0

Заглядывая в это решение ... – Mordachai

2

Вы можете использовать type erasure для прозрачного просмотра всех версий FilePointerT. Как упоминалось выше, я также хотел бы использовать подход shared_ptr, ведь дебелтор даже не является частью сигнатуры shared_ptr, поэтому вы сможете изменять делетитель, сохраняя постоянный тип.

+0

+1 для стирания типа, как и почему решение 'shared_ptr' работает в конце концов. –