operator <<를 오버로딩 할 때 std :: endl은 알 수없는 유형입니다.
나는 연산자 << 오버로드
template <Typename T>
UIStream& operator<<(const T);
UIStream my_stream;
my_stream << 10 << " heads";
작동하지만 :
my_stream << endl;
컴파일 오류를 제공합니다.
오류 C2678 : 바이너리 '<<': 'UIStream'유형의 왼쪽 피연산자를 사용하는 연산자를 찾을 수 없습니다 (또는 허용 가능한 변환이 없음).
작품을 만들기위한 작업은 무엇입니까 my_stream << endl
?
std::endl
은 함수이며 std::cout
.NET 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;
you'll like the compiler to deduce the template parameters for the operator as well as for endl
. This isn't possible.
So you have to write additional, non template, overloads of operator <<
to work with manipulators. Their prototype will look like:
UIStream& operator<<(UIStream& os, std::ostream& (*pf)(std::ostream&));
(there are two others, replacing std::ostream
by std::basic_ios<char>
and std::ios_base
, which you have also to provide if you want to allow all manipulators) and their implementation will be very similar to the one of your templates. In fact, so similar that you can use your template for implementation like this:
typedef std::ostream& (*ostream_manipulator)(std::ostream&);
UIStream& operator<<(UIStream& os, ostream_manipulator pf)
{
return operator<< <ostream_manipulator> (os, pf);
}
A final note, often writing a custom streambuf
is often a better way to achieve what one try to achieve applying to technique you are using.
I did this to solve my problem, here is part of my code:
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;
}
Main.cpp
int main(){
CFileLogger log();
log << "[WARNINGS] " << 10 << std::endl;
log << "[ERRORS] " << 2 << std::endl;
...
}
I got the reference in here http://www.cplusplus.com/forum/general/49590/
Hope this can help someone.
See here for better ways of extending IOStreams. (A bit outdated, and tailored for VC 6, so you will have to take it with a grain of salt)
The point is that to make functors work (and endl, which both outputs "\n" and flushes is a functor) you need to implement the full ostream interface.
The std
streams are not designed to be subclassed as they have no virtual methods so I don't think you'll get too far with that. You can try aggregating a std::ostream to do the work though.
To make endl
work you need to implement a version of operator<<
that takes a pointer-to-function as that is how the manipulators such as endl
are handled i.e.
UStream& operator<<( UStream&, UStream& (*f)( UStream& ) );
or
UStream& UStream::operator<<( UStream& (*f)( UStream& ) );
Now std::endl
is a function that takes and returns a reference to a std::basic_ostream so that won't work directly with your stream so you'll need to make your own version which calls through to the std::endl
version in your aggregated std::iostream
.
Edit: Looks likes GMan's answer is better. He gets std::endl
working too!
In addition to the accepted answer, with C++11 it is possible to overload operator<<
for the type:
decltype(std::endl<char, std::char_traits<char>>)
ReferenceURL : https://stackoverflow.com/questions/1134388/stdendl-is-of-unknown-type-when-overloading-operator
'programing tip' 카테고리의 다른 글
localStorage 대 sessionStorage 대 쿠키 (0) | 2020.12.24 |
---|---|
백업 슬라이드에서 페이지 번호 무시 (0) | 2020.12.15 |
jQuery를 사용하여 Span의 내용을 변경하는 방법은 무엇입니까? (0) | 2020.12.15 |
할당 내 자바 스크립트 AND 연산자 (0) | 2020.12.15 |
Javascript에서 배열을 뒤집는 가장 효율적인 방법은 무엇입니까? (0) | 2020.12.15 |