Рекомендации для C++ полиморфного бинарного интерфейса ввода-вывода с возможностью поиска

Я использовал std::istream и ostream в качестве полиморфного интерфейса для двоичного ввода-вывода с произвольным доступом в C++, но во многих отношениях он кажется неоптимальным:

  • 64-битные поиски не переносимы и подвержены ошибкам из-за ограничений streampos/streamoff; в настоящее время используется boost/iostreams/positioning.hpp как обходной путь, но требует бдительности
  • Отсутствующие операции, такие как усечение или расширение файла (аналог POSIX ftruncate)
  • Несоответствие между конкретными реализациями; например stringstream имеет независимые позиции получения/пута, тогда как filestream не имеет
  • Несоответствие между реализациями платформы; например поведение при поиске конца файла или использование failbit/badbit при ошибках
  • Не нужны все средства форматирования stream или, возможно, даже буферизация streambuf
  • streambuf отчеты об ошибках (т. е. исключения или возврат индикатора ошибки) предположительно зависит от реализации на практике

Мне нравится упрощенный интерфейс, предоставляемый Boost.Iostreams. Концепция устройства, но она представлена ​​в виде шаблонов функций, а не полиморфного класса. (Существует device класс, но он не полиморфен и является просто вспомогательным классом реализации, который не обязательно используется в поставляемых реализациях устройств.) Я в основном использую большие файлы на диске, но мне действительно нужен полиморфизм, поэтому я могу легко заменить альтернативные реализации (например, использовать stringstream вместо fstream для модульные тесты) без всей сложности и связи времени компиляции глубокого создания экземпляра шаблона.

Есть ли у кого-нибудь рекомендации стандартного подхода к этому? Вроде обычная ситуация, так что не хочется изобретать свои интерфейсы без надобности. Например, что-то вроде java.nio.FileChannel кажется идеальным.

Мое лучшее решение на данный момент — поместить тонкий полиморфный слой поверх устройств Boost.Iostreams. Например:

class my_istream
{
public:
    virtual std::streampos seek(stream_offset off, std::ios_base::seekdir way) = 0;
    virtual std::streamsize read(char* s, std::streamsize n) = 0;
    virtual void close() = 0;
};

template <class T>
class boost_istream : public my_istream
{
public:
    boost_istream(const T& device) : m_device(device)
    {
    }

    virtual std::streampos seek(stream_offset off, std::ios_base::seekdir way)
    {
        return boost::iostreams::seek(m_device, off, way);
    }

    virtual std::streamsize read(char* s, std::streamsize n)
    {
        return boost::iostreams::read(m_device, s, n);
    }

    virtual void close()
    {
        boost::iostreams::close(m_device);
    }

private:
    T m_device;
};

person Trevor Robinson    schedule 15.06.2010    source источник


Ответы (2)



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

person Trevor Robinson    schedule 12.07.2010