Почему std :: istream не берет на себя ответственность за свой поток потоков? - PullRequest
6 голосов
/ 18 января 2010

Я пишу какую-то библиотеку виртуальных файловых систем для видеоигр, например ROFS Middleware CRI Middleware (см. Wikipedia ). Мое намерение с библиотекой состоит в том, чтобы предоставить естественные средства доступа к ресурсам разрабатываемых мной игр, которые хранят некоторые данные, встроенные в исполняемый файл, некоторые на носителе, а некоторые - на жестком диске локального пользователя (предпочтения, сохранение файлов игры и т. Д.) .

Доступ к таким ресурсам должен быть таким же простым, как и звонок типа

std::auto_ptr<std::istream> defaultConfigIStream(
    fslib.inputStream("self://defaultConfig.ini"));
std::auto_ptr<std::ostream> defaultConfigOStream(
    fslib.outputStream("localappdata://config.ini"));

// Copies default configuration to local user's appdata folder
defaultConfigIStream >> defaultConfigOStream;

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

Что я хочу знать, так это как я могу вернуть auto_ptr<> (или unique_ptr<>, вы выбираете), учитывая, что std::streambuf<>, связанный с std::[i/o]stream<>, не удаляется им при его уничтожении.

Я считаю, что std::[i/o]stream<> не предполагает владения над потоковым буфером, переданным ему при создании, так как конструктор не представляет семантику передачи владения, а в ссылке Apache на STDCXX не упоминается передача прав владения (и при этом ни один из ссылки на stdlib, которые я нашел в интернете).

Какие у меня есть альтернативы? Я мог бы также вернуть общий указатель и продолжать наблюдать за ним, пока менеджер FSlib не сохранит уникальную копию общего указателя, и в этом случае он уничтожит свою уникальную копию, а также потоковую буферизацию. Это практично, учитывая организационную модель библиотеки, но это не очень элегантно и не эффективно в этом отношении.

Я попытался взглянуть на Boost.Iostreams, но мне кажется, что с ним все еще хуже, поскольку у самих потоков типы устройств сильно привязаны к их типу (устройство для потока должно быть определено в его параметр шаблона). Эта проблема, по-видимому, делает использование Boost.Iostreams неосуществимым для моей библиотеки, поскольку необходимо абстрагировать конкретную реализацию потоков «источник / приемник», чтобы потоки можно было легко использовать для открытия файла, расположенного внутри самого исполняемого файла, например, внутри файла из файловой системы системы или внутри файла архивного типа.

Я мог бы написать контейнерный класс, который обрабатывает эти проблемы, но я бы предпочел сделать это более аккуратно (т.е. просто вернуть поток уже; это все, что ему нужно!;).

Предложения

1 Ответ

8 голосов
/ 18 января 2010

Вы можете просто получить свои собственные потоковые классы из istream соотв. ostream, установить буфер в конструкторе и уничтожить его в деструкторе.

Что-то вроде:

class config_istream : public std::istream {
public:
    config_istream(std::string name) : 
      std::istream(fslib.InputStream(name.c_str())) 
    {
    }

    ~config_istream() { delete rdbuf(); }
};

Посмотрите, как реализованы классы fstream, они решают аналогичную проблему (filebuf необходимо удалить вместе с fstream)

...