预处理器,未定义时将宏展开为空
Preprocessor, expand macro to nothing when undefined
预处理器对我来说一直是黑魔法,但我想我终于需要使用它了。
我已经实现了一个记录器 class 如果未设置标志,我想有条件地(编译标志)扩展为空,这样我就不会在生产中获得所有打印件。
这会有一个像这样的用例
FO_LOG << name() << "Hello World" << std::endl;
我以为我可以这样定义它
#ifdef TRACE
#define FO_LOG {return Faceoff::trace::log();}
#else
#define FO_LOG \
if(false){\
return Faceoff::trace::log();\
}
#endif
但这不会编译并出现以下错误
no viable conversion from returned value of type 'Faceoff::trace' to function return type 'int'
FO_LOG << name() << "omitted" << std::endl;
^~~~~~
/omitted/include/globals.h:69:16: note: expanded from macro 'FO_LOG'
return Faceoff::trace::log();\
^~~~~~~~~~~~~~~~~~~~~
现在错误清楚了,但我不知道如何用预处理器语法表达我的意图...
给你:
class devnull : public std::ostream {
class devnullbuff : public std::streambuf {
public:
int overflow( int c ) { return c; }
} m_nb;
public:
devnull() : std::ostream( &m_nb ) {}
};
#ifdef TRACE
#define FO_LOG Faceoff::trace::log()
#else
#define FO_LOG devnull()
#endif
假设 Faceoff::trace::log() returns 某种 ostream,那么你可以做你想做的事:
FO_LOG << name() << "Hello World" << std::endl;
这不是很有效,因为它每次都会创建一个新的 devnull 对象。您可以在您的程序中只创建一次并转发声明以避免这种情况。虽然没有那么优雅。
预处理器对我来说一直是黑魔法,但我想我终于需要使用它了。
我已经实现了一个记录器 class 如果未设置标志,我想有条件地(编译标志)扩展为空,这样我就不会在生产中获得所有打印件。
这会有一个像这样的用例
FO_LOG << name() << "Hello World" << std::endl;
我以为我可以这样定义它
#ifdef TRACE
#define FO_LOG {return Faceoff::trace::log();}
#else
#define FO_LOG \
if(false){\
return Faceoff::trace::log();\
}
#endif
但这不会编译并出现以下错误
no viable conversion from returned value of type 'Faceoff::trace' to function return type 'int'
FO_LOG << name() << "omitted" << std::endl;
^~~~~~
/omitted/include/globals.h:69:16: note: expanded from macro 'FO_LOG'
return Faceoff::trace::log();\
^~~~~~~~~~~~~~~~~~~~~
现在错误清楚了,但我不知道如何用预处理器语法表达我的意图...
给你:
class devnull : public std::ostream {
class devnullbuff : public std::streambuf {
public:
int overflow( int c ) { return c; }
} m_nb;
public:
devnull() : std::ostream( &m_nb ) {}
};
#ifdef TRACE
#define FO_LOG Faceoff::trace::log()
#else
#define FO_LOG devnull()
#endif
假设 Faceoff::trace::log() returns 某种 ostream,那么你可以做你想做的事:
FO_LOG << name() << "Hello World" << std::endl;
这不是很有效,因为它每次都会创建一个新的 devnull 对象。您可以在您的程序中只创建一次并转发声明以避免这种情况。虽然没有那么优雅。