std:: endl имеет неизвестный тип при перегрузке оператора
Я перегруженный оператор
template <Typename T>
UIStream& operator<<(const T);
UIStream my_stream;
my_stream << 10 << " heads";
работает, но:
my_stream << endl;
дает ошибку компиляции:
ошибка C2678: двоичный'
что такое работа вокруг для создания my_stream << endl
работы?
6 ответов:
std::endl
функция иstd::cout
использует его реализацииoperator<<
чтобы взять указатель функции с той же сигнатурой, что иstd::endl
.там, он вызывает функцию и передает возвращаемое значение.
вот пример кода:
#include <iostream> struct MyStream { template <typename T> 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<char, std::char_traits<char> > 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
. Это невозможно.таким образом, вы должны написать дополнительные, не шаблон, перегрузки оператора
<<
to работа с манипуляторами. Их прототип будет выглядеть так:UIStream& operator<<(UIStream& os, std::ostream& (*pf)(std::ostream&));
(есть еще два, заменяющие
std::ostream
bystd::basic_ios<char>
иstd::ios_base
, который вы должны предоставить, если вы хотите, чтобы все манипуляторы) и их реализация будет очень похожа на одну из ваш шаблон. На самом деле, так похоже, что вы можете использовать свой шаблон для реализация такова:typedef std::ostream& (*ostream_manipulator)(std::ostream&); UIStream& operator<<(UIStream& os, ostream_manipulator pf) { return operator<< <ostream_manipulator> (os, pf); }
заключительная нота, часто пишущая пользовательский
streambuf
часто лучший способ достигните того, чего вы пытаетесь достичь, применяя технику, которую вы используете.
Я сделал это, чтобы решить мою проблему, вот часть моего кода:
template<typename T> CFileLogger &operator <<(const T value) { (*this).logFile << value; return *this; } CFileLogger &operator <<(std::ostream& (*os)(std::ostream&)) { (*this).logFile << os; return *this; }
Главная.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" и сбрасывает функтор) вам нужно реализовать полный интерфейс ostream.
The
std
потоки не предназначены для подклассов, поскольку у них нет виртуальных методов, поэтому я не думаю, что вы зайдете слишком далеко с этим. Вы можете попробовать агрегировать std::ostream, чтобы выполнить эту работу.сделать
endl
работа вам нужно реализовать версиюoperator<<
что принимает указатель на функцию, как это, как манипуляторы, такие какendl
обрабатываются, т. е.UStream& operator<<( UStream&, UStream& (*f)( UStream& ) );
или
UStream& UStream::operator<<( UStream& (*f)( UStream& ) );
теперь
std::endl
- это функция, которая принимает и возвращает ссылку на std:: basic_ostream, так что не будет работать непосредственно с потоком, так что вам нужно будет сделать свою собственную версию, которая вызывает черезstd::endl
версия в сводныеstd::iostream
.Edit: похоже, ответ GMan лучше. Он получает
std::endl
тоже работает!