Наследование от std:: basic streambuf для записи в сокет
Я хотел бы написать собственную библиотеку журналов, которая обеспечивает абстракцию для того, куда отправляются записи журнала.
библиотека ввода-вывода C++ уже предоставляет такую абстракцию с std::stringstream
и std::fstream
. Я также хотел бы иметь возможность читать/писать из/в сокет.
Я читал, что правильный способ расширения стандартной библиотеки наследуются от std::basic_streambuf
. Чего я не понимаю, так это, если наследование от std::basic_streambuf
как std::basic_filebuf
делает, где находится потребность в std::ifsream
, std::ofstream
и std::fstream
классы ? Не могу ли я просто заменить буфер некоторого потока экземпляром подкласса std::basic_streambuf
какие выходы, где я хочу ?
до сих пор я делал следующее, Но я действительно не уверен в том, что я делаю. Следующая конструкция правильная ?
template< typename char_type, typename traits_type = std::char_traits< char_type > >
class basic_sock_streambuf : public std::basic_streambuf< char_type, traits_type >
{
public:
basic_sock_streambuf()
{
}
~basic_sock_streambuf()
{
}
int overflow (int c = EOF)
{
fputc( c, stdout ); // Temporary.
return traits_type::to_int_type( c );
}
int underflow()
{
return fgetc( stdout ); // Temporary.
}
int sync()
{
return 0;
}
};
template< typename char_type, typename traits_type = std::char_traits< char_type > >
class basic_isockstream : public std::basic_istream< char_type, traits_type >
{
};
template< typename char_type, typename traits_type = std::char_traits< char_type > >
class basic_osockstream : public std::basic_ostream< char_type, traits_type >
{
};
template< typename char_type, typename traits_type = std::char_traits< char_type > >
class basic_socktream : public basic_isockstream< char_type, traits_type >, public basic_osockstream< char_type, traits_type >
{
private:
typedef basic_isockstream< char_type, traits_type > iparent;
typedef basic_osockstream< char_type, traits_type > oparent;
basic_sock_streambuf< char_type, traits_type > sock_sb;
std::basic_streambuf< char_type, traits_type > * old_isb;
std::basic_streambuf< char_type, traits_type > * old_osb;
public:
basic_socktream()
{
old_isb = iparent::rdbuf( & sock_sb );
old_osb = oparent::rdbuf( & sock_sb );
}
~basic_socktream() throw()
{
iparent::rdbuf( old_isb );
oparent::rdbuf( old_osb );
}
};
EDIT: код обновлен на основе ответов:
template<
typename char_type,
typename traits_type = std::char_traits< char_type > >
class basic_sockbuf :
public std::basic_streambuf< char_type, traits_type >
{
public:
basic_sockbuf()
{
}
~basic_sockbuf()
{
}
int overflow( int c = EOF )
{
fputc( c, stdout ); // Temporary.
return traits_type::to_int_type( c );
}
int underflow()
{
return fgetc( stdout ); // Temporary.
}
int sync()
{
return 0;
}
};
template<
typename char_type,
typename traits_type = std::char_traits< char_type > >
class basic_isockstream :
public std::basic_istream< char_type, traits_type >
{
private:
typedef std::basic_istream< char_type, traits_type > parent;
basic_sockbuf< char_type, traits_type > buffer;
public:
basic_isockstream() :
std::basic_istream< char_type, traits_type >::basic_istream(),
buffer()
{
init( & buffer );
}
};
template<
typename char_type,
typename traits_type = std::char_traits< char_type > >
class basic_osockstream :
public std::basic_ostream< char_type, traits_type >
{
private:
basic_sockbuf< char_type, traits_type > buffer;
public:
basic_osockstream() :
std::basic_ostream< char_type, traits_type >::basic_istream(),
buffer()
{
init( & buffer );
}
};
template<
typename char_type,
typename traits_type = std::char_traits< char_type > >
class basic_socktream :
public std::basic_iostream< char_type, traits_type >,
public basic_sockbuf< char_type, traits_type >
{
private:
basic_sockbuf< char_type, traits_type > buffer;
public:
basic_socktream() :
std::basic_iostream< char_type, traits_type >::basic_iostream(),
buffer()
{
std::basic_iostream< char_type, traits_type >::init( & buffer );
}
};
1 ответов
std::istream
и std::ostream
обеспечить форматированные операции ввода и вывода. То есть преобразование потока в/из чисел, строк и т. д...
std::basic_streambuf
- это интерфейс нижнего уровня, который считывает или записывает фрагменты символов В или из ...где-то. Это то, что вам нужно для подкласса и реализации.
и вы на правильном пути. Оба!--0--> и std::ostream
имеют перегруженный конструктор, который принимает указатель на буфер потока. Итак, ваш план действий есть:
подкласс и реализовать свой пользовательский
std::basic_streambuf
.построить
std::istream
илиstd::ostream
использование указателя на буфер потока.
не могу ли я просто заменить буфер некоторого потока экземпляром подкласс std::basic_streambuf
нет, не заменить, а построить. Вы создаете std::istream
или std::ostream
, используя указатель на свой буфер. Вы не будете используйте std::[io]fstream
, а std::istream
и std::ostream
, построен с использованием буфера потока.
все это a std::ifstream
is, например, является подклассом std::istream
который создает свой суперкласс с указателем на внутренний буфер потока, который считывает из файла.
не стесняйтесь создавать свой собственный подкласс std::istream
, который multiply-наследуется от вашего подкласса буфера потока, и std::istream
, сначала создает подкласс буфера потока, затем std::istream
.