最近我一直在阅读Scott Meyers撰写的《Effective C++第二版》,以提高C++最佳实践。他列举了其中一个条目,鼓励C++程序员避免使用预处理宏,并“更喜欢编译器”。他甚至说除了#include和#ifdef / #ifndef之外,在C ++中几乎没有宏的理由。
我同意他的推理,因为你可以通过以下方式实现宏
#define min(a,b) ((a) < (b) ? (a) : (b))
使用以下C++语言特性
template<class T>
inline const T & min(const T & a, const T & b) {
return a < b ? a : b;
}
使用inline关键字可以使编译器有选择地移除函数调用并插入内联代码和模板,以处理具有重载或内置>操作符的多个数据类型。
编辑-- 如果a和b的数据类型不同,则此模板声明将不能完全匹配所述的宏。请参见Pete的评论以获取示例。
然而,我很想知道在C++中是否可以使用宏进行调试日志记录。如果我下面提出的方法不是良好的实践,那么是否有人能够建议替代方法?
在过去的一年里,我一直在编写Objective-C,并且我的最喜欢的2D引擎(cocos2d)利用宏创建日志语句。该宏如下:
/*
* if COCOS2D_DEBUG is not defined, or if it is 0 then
* all CCLOGXXX macros will be disabled
*
* if COCOS2D_DEBUG==1 then:
* CCLOG() will be enabled
* CCLOGERROR() will be enabled
* CCLOGINFO() will be disabled
*
* if COCOS2D_DEBUG==2 or higher then:
* CCLOG() will be enabled
* CCLOGERROR() will be enabled
* CCLOGINFO() will be enabled
*/
#define __CCLOGWITHFUNCTION(s, ...) \
NSLog(@"%s : %@",__FUNCTION__,[NSString stringWithFormat:(s), ##__VA_ARGS__])
#define __CCLOG(s, ...) \
NSLog(@"%@",[NSString stringWithFormat:(s), ##__VA_ARGS__])
#if !defined(COCOS2D_DEBUG) || COCOS2D_DEBUG == 0
#define CCLOG(...) do {} while (0)
#define CCLOGWARN(...) do {} while (0)
#define CCLOGINFO(...) do {} while (0)
#elif COCOS2D_DEBUG == 1
#define CCLOG(...) __CCLOG(__VA_ARGS__)
#define CCLOGWARN(...) __CCLOGWITHFUNCTION(__VA_ARGS__)
#define CCLOGINFO(...) do {} while (0)
#elif COCOS2D_DEBUG > 1
#define CCLOG(...) __CCLOG(__VA_ARGS__)
#define CCLOGWARN(...) __CCLOGWITHFUNCTION(__VA_ARGS__)
#define CCLOGINFO(...) __CCLOG(__VA_ARGS__)
#endif // COCOS2D_DEBUG
这个宏提供了非常实用的功能,我希望能将其融入我的C++程序中。编写有用的日志语句就像这样简单:
CCLOG(@"Error in x due to y");
更棒的是,如果将COCOS2D_DEBUG设置为0,则这些语句永远不会被执行。检查条件语句以查看是否应使用日志记录语句,不会产生额外开销。在从开发环境过渡到生产环境时非常方便。如何在C++中重新创建这种效果?
那么,这种类型的宏适用于C++程序吗?有没有更好的、更符合C++风格的方法来实现这一点?
min(1, 2L)
。 - Pete Beckermin
在标准库中被定义的方式。 - Pete Becker