std :: endl неизвестного типа при перегрузке оператора <<

Я перегрузил оператора <<

template  UIStream& operator<<(const T); UIStream my_stream; my_stream << 10 << " heads"; 

Работает, но:

 my_stream << endl; 

Дает ошибку компиляции:

ошибка C2678: двоичный ‘<<': оператор не найден, который берет левый операнд типа 'UIStream' (или нет приемлемого преобразования)

Какова работа для создания my_stream << endl работы?

std::endl – это функция, и std::cout использует ее, реализуя operator<< чтобы взять указатель на функцию с той же сигнатурой, что и std::endl .

Там он вызывает функцию и пересылает возвращаемое значение.

Вот пример кода:

 #include  struct MyStream { template  MyStream& operator<<(const T& x) { std::cout << x; return *this; } // function that takes a custom stream, and returns it typedef MyStream& (*MyStreamManipulator)(MyStream&); // take in a function with the custom signature MyStream& operator<<(MyStreamManipulator manip) { // call the function, and return it's value return manip(*this); } // define the custom endl for this stream. // note how it matches the `MyStreamManipulator` // function signature static MyStream& endl(MyStream& stream) { // print a new line std::cout << std::endl; // do other stuff with the stream // std::cout, for example, will flush the stream stream << "Called MyStream::endl!" << std::endl; return stream; } // this is the type of std::cout typedef std::basic_ostream > CoutType; // this is the function signature of std::endl typedef CoutType& (*StandardEndLine)(CoutType&); // define an operator<< to take in std::endl MyStream& operator<<(StandardEndLine manip) { // call the function, but we cannot return it's value manip(std::cout); return *this; } }; int main(void) { MyStream stream; stream << 10 << " faces."; stream << MyStream::endl; stream << std::endl; return 0; } 

Надеюсь, это даст вам лучшее представление о том, как это работает.

Проблема в том, что std::endl – это шаблон функции, так как ваш оператор << . Поэтому, когда вы пишете:

 my_stream << endl; 

вам понравится компилятору вывести параметры шаблона для оператора, а также для endl . Это невозможно.

Поэтому вам нужно написать дополнительные, не шаблонные, перегрузки оператора << для работы с манипуляторами. Их прототип будет выглядеть так:

 UIStream& operator<<(UIStream& os, std::ostream& (*pf)(std::ostream&)); 

(есть еще два, заменив std::ostream на std::basic_ios и std::ios_base , которые вы также должны предоставить, если хотите разрешить все манипуляторы), и их реализация будет очень похожа на ваши шаблоны. На самом деле, так что вы можете использовать свой шаблон для реализации следующим образом:

 typedef std::ostream& (*ostream_manipulator)(std::ostream&); UIStream& operator<<(UIStream& os, ostream_manipulator pf) { return operator<<  (os, pf); } 

Последнее замечание, часто пишущее пользовательский streambuf , часто является лучшим способом достижения того, что можно попытаться применить к используемой вами технике.

Я сделал это, чтобы решить свою проблему, вот часть моего кода:

  template CFileLogger &operator <<(const T value) { (*this).logFile << value; return *this; } CFileLogger &operator <<(std::ostream& (*os)(std::ostream&)) { (*this).logFile << os; return *this; } 

main.cpp

 int main(){ CFileLogger log(); log << "[WARNINGS] " << 10 << std::endl; log << "[ERRORS] " << 2 << std::endl; ... } 

Я получил ссылку здесь: http://www.cplusplus.com/forum/general/49590/

Надеюсь, это может помочь кому-то.

См. Здесь, чтобы улучшить способы расширения IOStreams. (Немного устаревший и адаптированный для VC 6, поэтому вам придется брать его с солью)

Дело в том, что для работы функторов (и endl, которые оба выхода «\ n» и flushes являются функторами), вам необходимо реализовать полный интерфейс ostream.

std streamи не предназначены для подclassа, поскольку у них нет виртуальных методов, поэтому я не думаю, что вы слишком забудете это. Однако вы можете попытаться объединить std :: ostream для выполнения работы.

Чтобы выполнить работу endl вам необходимо реализовать версию operator<< которая принимает указатель на функцию, так как обрабатываются манипуляторы, такие как endl , т.е.

 UStream& operator<<( UStream&, UStream& (*f)( UStream& ) ); 

или

 UStream& UStream::operator<<( UStream& (*f)( UStream& ) ); 

Теперь std::endl - это функция, которая берет и возвращает ссылку на std :: basic_ostream, поэтому она не будет работать непосредственно с вашим streamом, поэтому вам нужно будет сделать свою собственную версию, которая вызывает версию std::endl в вашем агрегированном std::iostream .

Редактировать: Похоже, что ответ GMan лучше. Он тоже работает std::endl !

В дополнение к принятому ответу, с C ++ 11 можно перегрузить operator<< для типа:

 decltype(std::endl>) 
  • Как я должен писать стандартные стандартные и удаленные операторы ISO C ++ Standard?
  • Есть ли способ перегрузки методов в TypeScript?
  • Почему бы заменить операторы нового и удаления по умолчанию?
  • Как перегрузить унарный минус-оператор в C ++?
  • Перегрузка операторов доступа членов ->,. * (C ++)
  • Операторы перегрузки как функция-член или функция не-член (друга)?
  • Почему вы не можете перегрузить '.' оператора в C ++?
  • Почему оператор присваивания возвращает ссылку на объект?
  • перегрузка оператора друга << для шаблона classа
  • Каков правильный способ перегрузить operator == для иерархии classов?
  • Довольно печатные контейнеры STL STL
  • Interesting Posts

    Что эквивалентно getLastInsertId () в CakePHP?

    Как закрыть приложения с помощью веб-камеры webcam dell?

    Не удается установить гостевые дополнения с помощью VirtualBox, гостевой ОС Ubuntu, операционной системы Win7

    Knockout.js без контейнера «foreach» не работает с

    Удаление дубликатов файлов, сохранение только самого нового файла

    VBA делает ячейки обязательными на основе предыдущей записи ячейки

    Как Ctrl-C завершает дочерний процесс?

    Должен ли я создавать резервные копии скрытого раздела в 100 МБ при создании образа диска с помощью Clonezilla?

    OSX: ssh: Не удалось разрешить имя хоста: nodename или servname предоставлено или неизвестно

    Объясните, как работает узел запуска цикла в циклическом списке?

    Быстрое решение для суммы подмножества

    Анонимные функции с использованием выражений операторов GCC

    Настройка 2 внешних мониторов на ноутбуке с VGA-разветвителем

    как реализовать как ontouch, так и onfling в одном списке?

    ForceAutoLogon Игнорируется в Windows 7 при настройке Autologin – Autologon

    Давайте будем гением компьютера.