как ofstream или ostream type преобразует все типы в string?
-
16-09-2019 - |
Вопрос
любой системный пользовательский тип, прошедший до объекта ostream, преобразуется в строку или символ * ?
как коут<<4<<"Привет, мир";
работает отлично, как это достигается?является ли << оператор перегружен для каждого типа?есть ли способ достичь этого с помощью всего лишь одной универсальной перегруженной функции?я имею в виду, могу ли я иметь только один перегруженный операторный метод с одним параметром (например, void *), а затем решить внутри этого метода, как преобразовать целое число в символ*
Все сработало частично, если я перегрузил operator << используя шаблон, т.е.
class UIStream
{
private:
ofstream stream;
public:
UIStream();
~UIStream();
template <typename T>
UIStream& operator << (const T);
};
итак, это работает
UIStream my_stream;
my_stream<<"bcd"<10;
однако это выдает ошибку компилятора, когда я делаю это
my_stream <<endl;
ошибка C2678:двоичный файл '<<' :не найден оператор, который принимает левый операнд типа 'UIStream' (или нет приемлемого преобразования)
Разве std::endl тоже не является типом объекта?
Решение
После повторного прочтения вашего вопроса (в результате комментария в этом ответ) Я понял, что то, что вы хотите, - это не только преобразования в строку (мои предположения в другом ответе здесь), а скорее перенаправление во внутренний ofstream.
Итак, то, чего вы хотите достичь, непросто и в большинстве случаев может оказаться излишеством.При осуществлении [make_string][3]
, который у меня есть (который пересылается во внутренний ostringstream
), я не допускаю, чтобы манипуляторы проходили мимо.Если пользователь хочет добавить новую строку (мы разрабатываем под Linux), он просто передает символ '\ n'.
Ваша проблема заключается в пересылке манипуляторов (std::hex
, std::endl
...).Ваш оператор<< определяется как использование постоянного экземпляра типа T, но манипуляторы являются указателями на функции, и компилятор не может сопоставить его с вашими методами.
Манипуляторы - это функции, которые действуют на std::basic_ostream
шаблон.Тот самый basic_ostream
шаблон и ostream
класс определяется как:
template <typename TChar, typename TTraits = char_traits<TChar> >
class basic_ostream;
typedef basic_ostream<char> ostream;
// or
// typedef basic_ostream<wchar_t> if using wide characters
Тогда возможными манипуляторами, которые могут быть переданы в std::ostream, являются:
typedef std::ostream& (*manip1)( std::ostream& );
typedef std::basic_ios< std::ostream::char_type, std::ostream::traits_type > ios_type;
typedef ios_type& (*manip2)( ios_type& );
typedef std::ios_base& (*manip3)( std::ios_base& );
Если вы хотите принимать манипуляторы, вы должны обеспечить эту перегрузку в своем классе:
class mystream
{
//...
public:
template <typename T>
mystream& operator<<( T datum ) {
stream << datum;
return *this
}
// overload for manipulators
mystream& operator<<( manip1 fp ) {
stream << fp;
return *this;
}
mystream& operator<<( manip2 fp ) {
stream << fp;
return *this;
}
mystream& operator<<( manip3 fp ) {
stream << fp;
return *this;
}
};
В частности, подпись для endl (которая может быть единственной, которая вам требуется) является:
template <typename Char, typename Traits>
std::basic_ostream<Char,Traits>&
std::endl( std::basic_ostream<Char,Traits>& stream );
таким образом, это подпадает под manip1
тип функций.Другие, такие как std::hex
подпадают под разные категории (manip3
в данном конкретном случае)
Другие советы
у меня есть только один перегруженный оператор метод с одним параметром (например, void *) и затем решите внутри этого метода, как преобразовать целое число в символ*
Нет, ты не можешь.Void * не содержит информации о типе, поэтому нет способа определить, на какой тип он на самом деле указывает.
Есть только одна перегруженная функция.Это не требует void *
, потому что это было бы бесполезно.Если он принимает один тип данных, он не перегружается и видит входное значение только после его преобразования в тип.Это означает, что вы не можете контролировать, как конвертировать, скажем, int
.
Если вам нужно разное поведение, скажем, между int
и char *
, вам нужно каким-то образом сообщить функции, какой тип она получает, и передать ей значение.Именно это и делает перегруженная или шаблонная функция.
перегружен ли оператор << для каждого типа?
да
Есть ли способ добиться этого с помощью всего лишь одной общей перегруженной функции?
этот вопрос не имеет смысла..вам нужна только одна функция или вам нужна перегруженная функция?