как тип ofstream или ostream переводит все типы в строку?

любой системный пользовательский тип, прошедший до объекта ostream, преобразуется в строку или char *?

наподобие cout ‹---------------- 4 ‹< "Hello World";

отлично работает, как это достигается? Перегружен ли оператор ‹< для каждого типа? есть ли способ добиться этого с помощью одной общей перегруженной функции? я имею в виду, могу ли я иметь только один перегруженный метод оператора с одним параметром (например, void *), а затем решить внутри этого метода, как преобразовать целое число в char *

Все сработало частично, если я перегрузил оператора ‹< с помощью шаблона, т.е.

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 тоже не является типом объекта?


person Kazoom    schedule 15.07.2009    source источник
comment
std :: endl - это шаблон функции, а не объект.   -  person eduffy    schedule 16.07.2009
comment
Вы не читали свой другой вопрос? Это дубликат: stackoverflow.com/questions/1134388/   -  person GManNickG    schedule 16.07.2009


Ответы (4)


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

То, чего вы хотите достичь, непросто, и в большинстве случаев может оказаться излишним. В реализации [make_string][3], которая у меня есть (которая пересылает внутреннюю ostringstream), я не разрешаю передавать манипуляторы. Если пользователь хочет добавить новую строку (мы разрабатываем под Linux), он просто передает символ '\ n'.

Ваша проблема - манипуляторы пересылки (std::hex, _4 _...). Ваш оператор ‹< определяется как принимающий постоянный экземпляр типа 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 в данном конкретном случае)

person David Rodríguez - dribeas    schedule 15.07.2009
comment
hex, dec, oct и т. д. все попадают в манип3, как вы отличите то, что на самом деле сделало вызов - person Kazoom; 08.08.2009
comment
Вам это нужно? Вы не просто передаете аргумент во внутренний поток? Библиотека их не различает, это просто указатели на функции. Перегрузка оператора ‹* в классе basic_stream вызовет функцию, передав this в качестве аргумента. - person David Rodríguez - dribeas; 09.08.2009
comment
спасибо, я пытаюсь использовать setw (), но, похоже, он не попадает ни в одну из этих трех категорий, какие-либо предложения по этому поводу? - person Kazoom; 02.10.2009
comment
setw особенный тем, что точный тип элемента, возвращаемого вызовом функции, определяется реализацией. В gcc вызов функции возвращает элемент типа _Setw, который представляет собой структуру, содержащую новую ширину. Теперь стандарт действительно определяет, что он должен быть эквивалентен вызову ios_base :: width, поэтому вы можете подумать об определении альтернативного способа перенаправления вызова во внутренний поток. - person David Rodríguez - dribeas; 02.10.2009

у меня есть только один перегруженный метод оператора с одним параметром (например, void *), а затем внутри этого метода решается, как преобразовать целое число в char *

Нет, не можешь. Void * не несет информации о типе, поэтому невозможно определить, на какой тип он фактически указывает.

person Community    schedule 15.07.2009

Есть всего одна перегруженная функция. Для этого не нужно void *, потому что это было бы бесполезно. Если он принимает один тип данных, он не перегружается и видит входное значение только после его преобразования в тип. Это означает, что вы не можете контролировать, как преобразовать, скажем, int.

Если вам нужно различное поведение, скажем, между int и char *, вам нужно каким-то образом сообщить функции, какой тип она получает, и вам нужно передать значение. Это именно то, что делает перегруженная или шаблонная функция.

person David Thornley    schedule 15.07.2009
comment
+1, но на самом деле это немного сложнее, поскольку в std есть перегруженная функция-член std::basic_ostream& std::basic_ostream::operator<<( ? ) (где? Повторяется для базовых типов и пары дополнительных версий, таких как указатели на функции, для работы с std :: endl и т.п.): : шаблон basic_ostream и бесплатный оператор ‹< 's: std::basic_ostream& operator<<( std::basic_ostream&, ? ) для пользовательских преобразований. Эти операторы не обязательно являются перегрузками, поскольку они могут быть (и в большинстве случаев таковыми не являются) определены в разных пространствах имен (для второго типа аргумента) - person David Rodríguez - dribeas; 16.07.2009
comment
@dribease, как показано в примере в вопросе, что мне делать, чтобы мой вызов перегруженного оператора принял std :: endl в качестве параметра? В настоящее время меня не беспокоят типы, определяемые пользователем, я хочу, чтобы мой класс вел себя как ostream только для типов, определенных системой - person Kazoom; 16.07.2009
comment
Если вы хотите, чтобы он вел себя как ostream, используйте ostream в форме ostringstream. Вы можете сделать это напрямую, получив строковое значение с помощью .str (), или создать функцию-шаблон, которая будет принимать значение любого типа, передавать его в поток ostring и возвращать строковое значение. - person David Thornley; 16.07.2009

Перегружен ли оператор ‹< для каждого типа?

да

есть ли способ добиться этого с помощью одной общей перегруженной функции?

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

person eduffy    schedule 15.07.2009
comment
мой второй вопрос означал, могу ли я иметь только одну перегруженную функцию, которая может принимать только один параметр (что-то вроде void *), и чем я могу привести все, что передано перегруженному оператору внутри функции - person Kazoom; 16.07.2009
comment
Вы имеете в виду функцию шаблона? - person eduffy; 16.07.2009
comment
Я пытаюсь перекрыть ‹<, и я хочу, чтобы он вел себя как ostream, он должен иметь возможность принимать все типы, определенные системой, без каких-либо проблем - person Kazoom; 16.07.2009
comment
Вам, скорее всего, не повезло ... если вам нужно знать их типы, то вам придется перегрузить для каждого типа. Если вам просто нужно строковое представление вашего аргумента, возьмите аргумент шаблона и передайте его в std :: stringstream. Если вы не знакомы с шаблонами, вот очень легкое вступление: en.wikipedia.org / wiki / - person eduffy; 16.07.2009