The enum hack is worth knowing about for several reasons. First, the enum hack behaves in some ways more like a #define than a const does, and sometimes that’s what you want. For example, it’s legal to take the address of a const, but it’s not legal to take the address of an enum, and it’s typically not legal to take the address of a #define, either. If you don’t want to let people get a pointer or reference to one of your integral constants, an enum is a good way to enforce that constraint. (For more on enforcing design constraints through coding decisions, consult Item 18.) Also, though good compilers won’t set aside storage for const objects of integral types (unless you create a pointer or reference to the object), sloppy compilers may, and you may not be willing to set aside memory for such objects. Like #defines, enums never result in that kind of unnecessary memory allocation.
A second reason to know about the enum hack is purely pragmatic. Lots of code employs it, so you need to recognize it when you see it. In fact, the enum hack is a fundamental technique of template metaprogramming (see Item 48).
Getting back to the preprocessor, another common (mis)use of the #define directive is using it to implement macros that look like functions but that don’t incur the overhead of a function call. Here’s a macro that calls some function f with the greater of the macro’s arguments:
-
- #define CALL_WITH_MAX(a, b) f((a) > (b) (a) : (b))
Macros like this have so many drawbacks, just thinking about them is painful.
Whenever you write this kind of macro, you have to remember to parenthesize all the arguments in the macro body. Otherwise you can run into trouble when somebody calls the macro with an expression. But even if you get that right, look at the weird things that can happen:
max是永远的关于宏的反面案例。可悲的是,这里列出的template的解决方案也并非完美。有兴趣的同学可以在Google中搜索一篇题为min, max, and more的文章。那篇文章也正是本书作者Scott Meyers所写,你会惊叹把这么一件简单的事情做得完全正确是如此的困难。