TITLE: the flexibility of preprocessor directives PROBLEM: Adam Megacz In C++, #ifdef..#endifs can be used to cause conditional compilation of code. However, in "The C++ Programming Language", Soustrup suggests a better way: const int DEBUG = 1; if (DEBUG) { cout << "This is the debugging info...."; } Debugging can be shut off by altering the "const" declaration. Presumably, high end C++ compilers will optimize out the "if" statement, and the compiled application will never test "DEBUG" (since it is CONST). My question is, how common are such compilers that do this level of optimization. The method suggested above is much more flexible and elegant than #ifdefs, and on a good compiler, just as efficient. On a bad compiler, if this code appeared in the center of a performance-critical loop, it could cause slowdowns. So I'd like to know, do most C++ compilers optimize this out? Specifically, I'd like to know if gcc 2.7.2 does, and about what percentage of other compilers do. PROBLEM: A.Main@dcs.warwick.ac.uk (Zefram) Actually it's a lot *less* flexible than the preprocessor. Try doing #ifdef BSDISH_SYSTEM pg = getpgrp(0); #else pg = getpgrp(); #endif without the preprocessor. RESPONSE: clamage@Eng.Sun.COM (Steve Clamage), 24 Mar 96 That really isn't hard. It does take some analysis of what your program is trying to accomplish. For example, the Sun C++ compiler front end is used for three different operating systems for several different CPU's, and behaves differently when it is used a part of a browser than as a compiler. The differences were at one time handled by conditional compilation like the above. The code gradually became so baroque that it was in danger of becoming unmaintainable. Conditional compilation was banned, and the code was modified so as not to need it, without sacrificing performance, readability, or maintainability. In fact, the maintainability was greatly enhanced. A major source of bugs had been trying to figure out what code was actually executed and how to fit a modification into intertwined versions. That source of bugs disappeared. And of course the main-line source code is much more readable -- no conditional compilation. The general solution to a problem like the above is to define your own function that has behavior and interface suitable for any system of interest. You then implement that function in different ways for different purposes. Use parallel directories in the source tree to store identically-named source files containing the different implementations. Continuing the example, you define a function int mygetpgrp(int) which is implemented in different ways. In directory BDS_ISH: pid_t mygetpgrp(pid_t i) { return getpgrp(i); } In directory OTHER_UNIX: pid_t mygetpgrp(pid_t) { return getpgrp(); } // param not used In directory MSDOS: pid_t mygetpgrp(pid_t) { return 0; } // no such functionality The main code always calls "mygetpgrp" and doesn't need to be modified when you add more target systems. (Please, no arguments about the extra level of function call. If it matters, make the function inline and use parallel header files instead.) When you build for a target system, the system-dependent code resides in system-dependent directories, one of which is used for a particular build. The program builder ("make" or whatever) uses a symbolic name for the directory which is set in one place according to the target being built. To add another target, define new system- dependent code according to the established interface and put it in its own directory. No other code needs to be touched. C++ of course allows more ways to do this customizing: Define a base class with basic functionality implemented via virtual functions. Derive a new class for each target system. In real life, you have more problems: a new target system requires a different interface you didn't take into account, e.g. getpgrp requires three parameters instead of zero or one. You may have to modify the interface of mygetpgrp and all the implementations. But you probably would have equivalent problems using bad old conditional compilation anyway.