slp@genrad.uucp (Steven L. Peters) (07/02/90)
Just out of curiousity... With the C++ const, enum, and inline declarations, is it ever necessary to use #define in a C++ program? Stroustrup emphatically says in _The C++ Programming Language_ not to use them if you don't have to. I'm wondering if you ever have to. I can't think of a single time where you would be forced to use a #define over const or inline... Sorry if this was discussed before. Stephen Peters
petrilli@walt.cc.utexas.edu (Chris Petrilli) (07/02/90)
In article <37786@genrad.UUCP> slp@genrad.genrad.COM (Steven L. Peters) writes: >Just out of curiousity... > >With the C++ const, enum, and inline declarations, is it ever >necessary to use #define in a C++ program? Stroustrup emphatically >says in _The C++ Programming Language_ not to use them if you don't >have to. I'm wondering if you ever have to. I can't think of a >single time where you would be forced to use a #define over const or >inline... > The only time where you HAVE to use a #define (or at least, it is the best way for clarity) is in conditionally compiled code. For example: #define DEBUG #ifdef DEBUG ... (do something) ... #endif This would be more difficult under C++ convention of using constants, than the preprocessor, since you don't care about type, just whether it is defined or not. Hope this clarifies it... if someone can thing of another time where you HAVE to use the pre-processor, I'd like to know, I might be misusing/abusing C++. + Chris Petrilli "Opinons represented here | University of Texas at Austin do not necessarily | INTERNET: petrilli@vondrake.cc.utexas.edu represent those of a sane | SNAILMAIL: 429 Brady Lane, Austin, Texas, 78746 person. Take them as + PHONE: +1 512 327 0986 simply that."
philip@pescadero.Stanford.EDU (Philip Machanick) (07/02/90)
In article <37786@genrad.UUCP>, slp@genrad.uucp (Steven L. Peters) writes: > Just out of curiousity... > > With the C++ const, enum, and inline declarations, is it ever > necessary to use #define in a C++ program? Stroustrup emphatically > says in _The C++ Programming Language_ not to use them if you don't > have to. I'm wondering if you ever have to. I can't think of a > single time where you would be forced to use a #define over const or > inline... > Just a small example... errno, which contains an error number from the most recent error (used in a number of common libraries) is defined as an integer _expression_. It can for example be implemented as a function call. Could the same effect be achieved with any of the new constructs? I think not, because function calls and variable references are syntactically different in C/C++ (unlike some other languages, where a parameterless function looks like a variable reference). Philip Machanick philip@pescadero.stanford.edu
bright@Data-IO.COM (Walter Bright) (07/03/90)
In article <33133@ut-emx.UUCP> petrilli@walt.cc.utexas.edu (Chris Petrilli) writes:
<Hope this clarifies it... if someone can thing of another time where you HAVE
<to use the pre-processor, I'd like to know, I might be misusing/abusing
<C++.
You need the preprocessor's help if you wish to insert __FILE__ and __LINE__s
in the right spots. Using inline functions doesn't work because the __FILE__
and __LINE__ will expand to where the inline function is defined, not where
it is used. For example:
// Part of a package to track storage allocation
#define malloc(n) mem_malloc(n,__FILE__,__LINE__)
#define new ((__file__ = __FILE__),(__line__ = __LINE__)),new
Another use that I find particularly useful:
#if !(MSDOS || __OS2__)
#define cdecl
#define near
#define far /* make extended keywords go away */
#endif
Or how about conditionally making static functions global:
#ifdef DEBUG
#define STATIC /* make STATIC functions appear in .MAP file */
#else
#define STATIC static
#endif
STATIC int near function() { ... }
In other words, I think the preprocessor is here to stay.
Daniel_Gregory_Corbett@cup.portal.com (07/03/90)
Stephen Peters asks: >Just out of curiousity... > >With the C++ const, enum, and inline declarations, is it ever >necessary to use #define in a C++ program? Stroustrup emphatically >says in _The C++ Programming Language_ not to use them if you don't >have to. I'm wondering if you ever have to. I can't think of a >single time where you would be forced to use a #define over const or >inline... If you wish to use conditional compilation using #ifdef, and the like then #defines are required. const variables are not understood by cpp and are therefore ignored. Example: #define DEBUG /* This might be defined on the command line */ /* using -DDEBUG */ #ifdef DEBUG printf("Debug Statement i=%d\n", i); #endifk - Daniel
lerman@stpstn.UUCP (Ken Lerman) (07/03/90)
In article <37786@genrad.UUCP> slp@genrad.genrad.COM (Steven L. Peters) writes: [...] >With the C++ const, enum, and inline declarations, is it ever >necessary to use #define in a C++ program? Stroustrup emphatically >says in _The C++ Programming Language_ not to use them if you don't >have to. I'm wondering if you ever have to. I can't think of a >single time where you would be forced to use a #define over const or >inline... [...] > Stephen Peters The following is (more or less) taken from a real application #define GLOBAL(x) static char x[] = #x GLOBAL(reader); GLOBAL(writer); Generates: static char reader[] = "reader"; static char writer[] = "writer"; Without arguing the details, the point is that not every macro generates executable code. Functions cannot be used to create declarations, and "const" does not provide the terseness (be it good, bad, or indifferent) that macros provide. Ken
steve@taumet.com (Stephen Clamage) (07/03/90)
In article <1990Jul2.164355.15327@Neon.Stanford.EDU> philip@pescadero.stanford.edu writes: >Just a small example... errno, which contains an error number from >the most recent error (used in a number of common libraries) is defined >as an integer _expression_. It can for example be implemented as a >function call.... But errno is not C++, it is C. If you are required to use the C library and headers, then you have lots of macros forced on you. Realistically, any real C++ program written today will use the C library and at least some of the headers. But C++ provides better mechanisms for all the macro usages in C. -- Steve Clamage, TauMetric Corp, steve@taumet.com
ecsv38@castle.ed.ac.uk (S Manoharan) (07/03/90)
In article <37786@genrad.UUCP> slp@genrad.genrad.COM (Steven L. Peters) writes: >have to. I'm wondering if you ever have to. I can't think of a >single time where you would be forced to use a #define over const or >inline... 1. To avoid multiple inclusion of header files. 2. Macros local to a function. As in: #define _C(i,j) ( *(C + nelements * i + j) ) where C is <some> ptr, and _C(i, j) defines element [i, j] of an array. Note that an inline can't be local to a function. Mano.
steve@taumet.com (Stephen Clamage) (07/05/90)
In article <5005@castle.ed.ac.uk> ecsv38@castle.ed.ac.uk (S Manoharan) writes: >[when to use #define in C++] >1. To avoid multiple inclusion of header files. Thus creating a maintenance nightmare when one #define changes and another doesn't. >2. Macros local to a function. As in: >#define _C(i,j) ( *(C + nelements * i + j) ) >where C is <some> ptr, and _C(i, j) defines element [i, j] of an array. >Note that an inline can't be local to a function. But you can still do this with non-local inlines: inline SomeType *_C( SomeType *C, int nelements, int i, int j) { return C + nelements * i + j; } usage: ... + * _C(C, nelements, i, j) + ... * _C(C, nelements, i, j) = 0; This generates exactly the same code as the macro (for any reasonable compiler) and does not have the flaws of macros. Macros have no scope, and sometimes intrude where they are not wanted. Your example would have to start with #undef _C /* in case previously defined */ and end with #undef _C /* so it doesn't cause problems later */ But what if _C were defined as a global macro somewhere? It is now lost. If you don't use macros, they don't cause problems. I am not speaking of toy programs where one programmer holds the entire design in his head, but of real-world multi-programmer projects. A minor quibble: Identifiers beginning with an underscore and an uppercase letter are reserved. But that is irrelevant to this discussion. Second quibble: 2-dimensional arrays possibly could be used to avoid writing this code at all (but not in all applications). -- Steve Clamage, TauMetric Corp, steve@taumet.com
mckenney@sparkyfs.istc.sri.com (Paul Mckenney) (07/05/90)
In article <37786@genrad.UUCP> slp@genrad.genrad.COM (Steven L. Peters) writes: >Just out of curiousity... >With the C++ const, enum, and inline declarations, is it ever >necessary to use #define in a C++ program? Stroustrup emphatically >says in _The C++ Programming Language_ not to use them if you don't >have to. I'm wondering if you ever have to. I can't think of a >single time where you would be forced to use a #define over const or >inline... Until templates are commonly implemented, I will use macros in their stead. I also have used them in cases where I would use a nested function, if such a beast were available in C++. Macros have definite drawbacks, but so do functions with tons of parameters. The good news is that C++ classes can be used (abused?) to reduce the need for nested functions (as compared to C). The trick is to replace the top-level function with a class, with the class's instance variables serving in place of the function's local variables. The code that was in the function and in each local macro is then placed into a (possibly inlined) member function. There are still occasions where use of macros is cleaner, particularly if macro concatenation and stringification facilities come into play. Perhaps nested classes will do even better. Thanx, Paul
roger@zuken.co.jp (Roger Meunier) (07/05/90)
One thing I wish you could do with inline functions is declare global
variables with a name passed as an argument. For example, with #define
you can do the following:
typedef enum { Type1,Type2,Type3 } DataType;
class Data
{
DataType type;
int value;
...
}
#define MakeOrange(name,v) Data name = { Type1, v }
#define MakeApple(name,v) Data name = { Type2, v }
MakeOrange(fruit1,100);
MakeApple(fruit2,200);
How could you do this with an inline function? (If someone says,
"Use a constructor!" you've missed the point...)
--
Roger Meunier @ Zuken, Inc. Yokohama, Japan (roger@zuken.co.jp)
dan@dyndata.UUCP (Dan Everhart) (07/06/90)
In article <37786@genrad.UUCP> slp@genrad.uucp (Steven L. Peters) writes: > With the C++ const, enum, and inline declarations, is it ever > necessary to use #define in a C++ program? I don't know about *necessary* but I find it convenient to use the following: #if defined(DEBUG) #define pure { DebuggerTrap (); } #else #define pure = 0 #endif class Xyz { // ... virtual f () pure; // ... } This quickly finds erroneous calls of pure virtual functions during debugging, yet leaves no overhead in a production version. It's also highly readable. In article <PCG.90Jul2225948@odin.cs.aber.ac.uk> pcg@cs.aber.ac.uk (Piercarlo Grandi) writes: > arguable that 'this' (which should not exist, however) should be a > reference and not a pointer, but it's too late to change that. A #define comes in handy here too: #define self (*this) I don't think you could do either of these tricks without using a #define.
jlol@ALTAR.EE.BYU.EDU (Jay Lawlor) (07/07/90)
> With the C++ const, enum, and inline declarations, is it ever > necessary to use #define in a C++ program? Stroustrup emphatically > says in _The C++ Programming Language_ not to use them if you don't > have to. I'm wondering if you ever have to. I can't think of a > single time where you would be forced to use a #define over const or > inline... What about something like this? #define QUIT(err) { do_some_cleanup_stuff(); return(err); } With a macro, the return(err) returns from the function that invoked QUIT, but with an inline function you can only "return" back to the invoking function, right? Not that you couldn't return some other way, but I just thought of this when I was reading some code that used a similar #define. Jay
pcg@cs.aber.ac.uk (Piercarlo Grandi) (07/07/90)
In article <9007062136.AA08003@ucbvax.Berkeley.EDU> jlol@ALTAR.EE.BYU.EDU (Jay Lawlor) writes: > With the C++ const, enum, and inline declarations, is it ever > necessary to use #define in a C++ program? Stroustrup emphatically > says in _The C++ Programming Language_ not to use them if you don't > have to. I'm wondering if you ever have to. I can't think of a > single time where you would be forced to use a #define over const or > inline... What about something like this? #define QUIT(err) { do_some_cleanup_stuff(); return(err); } To settle the matter once and for all: macros are necessary to define new syntax forms; this is often undesirable, where the new syntax is merely a travesty of the old syntax, but is in some cases unavoidable. For example there is no other way to achieve *control* abstraction, because there is no such facility in the language for it. In the Lisp and Scheme family of languages macros are used like this too, even if they they have greater facilities to do control abstraction then the lonely setjmp/longjmp of C/C++. There are other cases where syntax abstraction is also justifiable; for example you may want to implement a state machine as a switch inside a for, but then you want to hide the implementation. Outside syntax abstraction the use of the preprocessor should be avoided. -- Piercarlo "Peter" Grandi | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk Dept of CS, UCW Aberystwyth | UUCP: ...!mcsun!ukc!aber-cs!pcg Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk
steve@taumet.com (Stephen Clamage) (07/08/90)
In article <9007062136.AA08003@ucbvax.Berkeley.EDU> jlol@altar.ee.byu.edu writes: >What about something like this? > >#define QUIT(err) { do_some_cleanup_stuff(); return(err); } We've now seen a lot of stuff on this thread where someone shows a macro which cannot be *precisely* duplicated with consts and inline functions. IMHO, the point is not to duplicate *precisely* what can be done with macros, but to write clear, concise, efficient code -- code which can be understood and maintained easily. So I must ask whether these macro examples fit these criteria better than other C++ language mechanisms. -- Steve Clamage, TauMetric Corp, steve@taumet.com
jef@well.sf.ca.us (Jef Poskanzer) (07/08/90)
In the referenced message, petrilli@walt.cc.utexas.edu (Chris Petrilli) wrote: }The only time where you HAVE to use a #define (or at least, it is the best }way for clarity) is in conditionally compiled code. For example: } }#define DEBUG } }#ifdef DEBUG } ... (do something) ... }#endif In many systems, the optimizers are smart enough to completely eliminate code under a compile-time false if statement. As in: const int debug = 0; if ( debug ) { (do something) } Or whatever. I have not checked whether this works in any C++ system, but I have used it in numerous other systems, after checking the generated machine instructions to be sure there was no run-time overhead. One big advantage of this over using the pre-processor is that the debugging code gets syntax-checked, so you avoid bit rot. One big disadvantage is that it doesn't work on all systems, so it can't be considered portable. --- Jef Jef Poskanzer jef@well.sf.ca.us {ucbvax, apple, hplabs}!well!jef A child of 5 could understand this! Fetch me a child of 5.
roger@procase.UUCP (Roger H. Scott) (07/11/90)
In article <37786@genrad.UUCP> slp@genrad.genrad.COM (Steven L. Peters) writes: >Just out of curiousity... > >With the C++ const, enum, and inline declarations, is it ever >necessary to use #define in a C++ program? Stroustrup emphatically >says in _The C++ Programming Language_ not to use them if you don't >have to. I'm wondering if you ever have to. I can't think of a >single time where you would be forced to use a #define over const or >inline... > Well, if C++ had types and functions as first-class-objects in the language your statement might have a chance of being true, but since C++ doesn't your statement doesn't. As a simple example, how would you write achieve the effect of a SWAP macro in C++? #define SWAP(T,a,b) {T t = a; a = b; b = t;} Until parameterized types come along (and they do the right thing), another example is generation of declarations of parameterized types. Another example is aliasing of identifier names in header files that you can't change, e.g.: read_only.h: class Foo { void dont_you_hate_this_lexical_style(); }; clean_it_up.c: #include "read_only.h" #define differentLexicalStyle dont_you_hate_this_lexical_style ... p->differentLexicalStyle(); This list is not exhaustive.
dsa@dlogics.COM (David Angulo) (07/17/90)
> In article <37786@genrad.UUCP> slp@genrad.genrad.COM (Steven L. Peters) writes: > >Just out of curiousity... > > > >With the C++ const, enum, and inline declarations, is it ever > >necessary to use #define in a C++ program? Stroustrup emphatically > >says in _The C++ Programming Language_ not to use them if you don't > >have to. I'm wondering if you ever have to. I can't think of a > >single time where you would be forced to use a #define over const or > >inline... > > Another example: use it for compiler directives. For example the #include can be commented out like thus: Module a: #ifndef a #define a ... // rest of module a ... #endif module b: #ifndef a #include "a.h" #endif ... // rest of module b -- David S. Angulo (312) 266-3134 Datalogics Internet: dsa@dlogics.com 441 W. Huron UUCP: ..!uunet!dlogics!dsa Chicago, Il. 60610 FAX: (312) 266-4473