문제
수업을 어떻게 도출 할 수 있습니까? cout
예를 들어 글을 쓰는 것입니다
new_cout << "message";
동등합니다
cout << __FUNCTION__ << "message" << "end of message" << endl;
해결책
class Log
{
public:
Log(const std::string &funcName)
{
std::cout << funcName << ": ";
}
template <class T>
Log &operator<<(const T &v)
{
std::cout << v;
return *this;
}
~Log()
{
std::cout << " [end of message]" << std::endl;
}
};
#define MAGIC_LOG Log(__FUNCTION__)
따라서:
MAGIC_LOG << "here's a message";
MAGIC_LOG << "here's one with a number: " << 5;
다른 팁
#define debug_print(message) (std::cout << __FUNCTION__ << (message) << std::endl)
이것은 완료되면 모든 디버그 메시지를 한 번에 비활성화 할 수 있다는 이점이 있습니다.
#define debug_print(message) ()
Mykola의 응답에서 나오면 코드에 다음과 같은 구현이 있습니다. 사용은입니다
LOG_DEBUG("print 3 " << 3);
인쇄물
DEBUG (f.cpp, 101): print 3 3
사용하도록 수정할 수 있습니다 기능 대신/대신 선 그리고 파일
/// Implements a simple logging facility.
class Logger
{
std::ostringstream os_;
static Logger* instance_;
Logger();
public:
static Logger* getLogger();
bool isDebugEnabled() const;
void log(LogLevelEnum l, std::ostringstream& os, const char* filename, int lineno) const;
std::ostringstream& getStream()
{ return os_; }
};
void Logger::log(LogLevelEnum l, std::ostringstream& os, const char* filename, int lineno) const
{
std::cout << logLevelEnumToString(l) << "\t(" << fileName << ": " << lineno << ")\t- " << os.str();
os.str("");
}
#define LOG_common(level, cptext) do {\
utility::Logger::getLogger()->getStream() << cptext; \
utility::Logger::getLogger()->log(utility::level, utility::Logger::getLogger()->getStream(), __FILE__, __LINE__); \
} while(0);
enum LogLevelEnum {
DEBUG_LOG_LEVEL,
INFO_LOG_LEVEL,
WARN_LOG_LEVEL,
ERROR_LOG_LEVEL,
NOTICE_LOG_LEVEL,
FATAL_LOG_LEVEL
};
#define LOG_DEBUG(cptext) LOG_common(DEBUG_LOG_LEVEL, cptext)
#define LOG_INFO(cptext) LOG_common(INFO_LOG_LEVEL , cptext)
#define LOG_WARN(cptext) LOG_common(WARN_LOG_LEVEL , cptext)
#define LOG_ERROR(cptext) LOG_common(ERROR_LOG_LEVEL, cptext)
#define LOG_NOTICE(cptext) LOG_common(NOTICE_LOG_LEVEL, cptext)
#define LOG_FATAL(cptext) LOG_common(FATAL_LOG_LEVEL, cptext)
const char* logLevelEnumToString(LogLevelEnum m)
{
switch(m)
{
case DEBUG_LOG_LEVEL:
return "DEBUG";
case INFO_LOG_LEVEL:
return "INFO";
case WARN_LOG_LEVEL:
return "WARN";
case NOTICE_LOG_LEVEL:
return "NOTICE";
case ERROR_LOG_LEVEL:
return "ERROR";
case FATAL_LOG_LEVEL:
return "FATAL";
default:
CP_MSG_ASSERT(false, CP_TEXT("invalid value of LogLevelEnum"));
return 0;
}
}
연산자 << ()를 무시해야하지만 std :: cout를 서브 클래스 할 필요조차 없습니다. 새 개체를 만들거나 이와 같은 기존 객체를 사용할 수도 있습니다.
로깅 목적으로 나는 같은 것을 사용합니다
#define LOG(x) \
cout << __FUNCTION__ << x << endl
// ...
LOG("My message with number " << number << " and some more");
귀하의 접근 방식의 문제는 (Mykola Golybyew가 설명했듯이) 기능 컴파일 타임에 처리되므로 항상 비 임금 솔루션으로 동일한 이름을 인쇄합니다.
메시지에 endl을 추가하기위한 것이라면 다음과 같은 것을 시도 할 수 있습니다.
class MyLine {
public:
bool written;
std::ostream& stream;
MyLine(const MyLine& _line) : stream(_line.stream), written(false) { }
MyLine(std::ostream& _stream) : stream(_stream), written(false) { }
~MyLine() { if (!written) stream << "End of Message" << std::endl; }
};
template <class T> MyLine operator<<(MyLine& line, const T& _val) {
line.stream << _val;
line.written = true;
return line;
}
class MyStream {
public:
std::ostream& parentStream;
MyStream(std::ostream& _parentStream) : parentStream(_parentStream) { }
MyLine getLine() { return MyLine(parentStream); }
};
template <class T> MyLine operator<<(MyStream& stream, const T& _val) {
return (stream.getLine() << _val);
}
int main()
{
MyStream stream(std::cout);
stream << "Hello " << 13 << " some more data";
stream << "This is in the next line " << " 1 ";
return 0;
}
연산자 함수에서 참조를 반환하지 않는 것이 중요합니다. 이후 MyLine
임시로만 존재해야합니다 (소멸자가 endl
)), 첫 번째 개체 ( getLine()
기능 MyStream
)는 두 번째 전에 파괴 될 것입니다 operator<<
호출됩니다. 따라서 MyLine
객체는 각각에 복사됩니다 operator<<
새로운 것을 만들었습니다. 마지막 물체는 소멸자에 메시지의 끝을 쓰지 않고 파괴됩니다.
무슨 일이 일어나고 있는지 이해하기 위해 디버거에서 시도해보십시오 ...
당신도 할 수 있습니다 연산자를 무시합니다. 다른 함수 또는 접두사/접미사를 호출 할 수 있습니다. 원하는대로 출력 버퍼를 남겨 두는 모든 것을 호출 할 수 있습니다. 귀하의 경우에는 특정 문자열을 출력 할 수 있습니다.