Thread View: comp.std.c++
6 messages
6 total messages
Started by Mark Russell
Fri, 16 Feb 1996 17:03
Article for comp.std.c++: Eliminating #ifdef: if const
Author: Mark Russell
Date: Fri, 16 Feb 1996 17:03
Date: Fri, 16 Feb 1996 17:03
87 lines
3150 bytes
3150 bytes
Subject: Eliminating #ifdef: if const
Here's an idea I had for a non-preprocessor replacement for #if and #ifdef.
if const (<expr>) { <stuff> }
`if const' is a compile time version of `if'. <expr> is a constant
expression which is convertible to bool. If it yields true, <stuff>
is processed as normal. Otherwise <stuff> is parsed into tokens, but
ignored except for counting { and } nesting. <stuff> is anything that
can appear inside a namespace block. `if const' does not introduce a
new scope.
The following is also legal, with the obvious meaning:
if const (<expr>) { <stuff> } else const { <other stuff> }
There are also a number of compile-time pseudo-functions (I hesitate
to call them pragmas):
bool #os_version(const char* str)
os version (uname -r) at or later than str
bool #os_name(const char *str)
os name (uname -s) is str
bool #compiler_name(const char *)
bool #compiler_version(const char*)
Same tests for the compiler
bool #header_exists(const char* path)
Would `#include <path>' succeed?
bool #have_test(const char* varname)
Would #varname(str) work (this would be useful to
allow testing for implementation defined tests.
Using these you could do things like this:
// Are we running IRIX 5.3
const bool using_irix_53 = #os_name("IRIX") &&
#os_version("5.3") && !#os_version("5.4")
if const (using_irix_53) {
// Do some stuff needed just for IRIX 5.3
}
if const (#compiler("g++")) {
// Do some g++ stuff
}
if const (#header_exists("sys/frobnitz9000.h")) {
#include "sys/frobnitz9000.h"
// Do stuff for the Frobnitz 9000
}
if const (#have_test("extension")) {
const bool have_foo_extension = #extension_exists("foo");
}
else const {
const bool have_foo_extension = false;
}
if const (have_foo_extension) {
// Stuff using the `foo' extension
}
With this I could personally stop using the preprocessor for anything
except #include. If `include' (as described in D&E) is also
implemented, I could stop using the preprocessor altogether, which
would be nice.
I realise this is too late for the upcoming version of the standard,
but I think it would be a useful thing for a subsequent version.
Comments?
Mark Russell
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy is
in http://reality.sgi.com/employees/austern_mti/std-c++/policy.html. ]
Re: Article for comp.std.c++: Eliminating #ifdef: if const
Author: Shankar Unni
Date: Mon, 19 Feb 1996 23:16
Date: Mon, 19 Feb 1996 23:16
52 lines
2561 bytes
2561 bytes
Mark Russell (M.T.Russell@ukc.ac.uk) wrote:
> Here's an idea I had for a non-preprocessor replacement for #if and #ifdef.
> if const (<expr>) { <stuff> }
> `if const' is a compile time version of `if'. <expr> is a constant
> expression which is convertible to bool. If it yields true, <stuff>
> is processed as normal. Otherwise <stuff> is parsed into tokens, but
> ignored except for counting { and } nesting. <stuff> is anything that
> can appear inside a namespace block. `if const' does not introduce a
> new scope.
No dice.
Often, an #ifdef covers just a small part of an expression that may be
different between different environments, or some such small differences:
if (some condition) {
#ifdef SOMEIMPL
if (some other condition) {
#endif /* SOMEIMPL */
/* code */
/* code */
/* code */
#ifdef SOMEIMPL
}
#endif /* SOMEIMPL */
}
Duplicating all the code so that each half is precisely correct in its {}
matching is both tedious and error-prone (trying to verify that both parts
of the expression are fixed).
Also, the #ifdefs serve a purpose in pointing out the fact that this piece
of code is system-dependent. The syntax you propose hides its warts rather
too well, and make it easy for a reader to miss the significant piece of
information that this area of code is system-dependent.
On the other hand, I'd really like to see function-like macros eased out
of usage..
--
Shankar Unni E-Mail: shankar@sgi.com
Silicon Graphics Inc. Phone: +1-415-933-2072
URL: http://reality.sgi.com/employees/shankar
[ To submit articles: Try just posting with your newsreader. If that fails,
use mailto:std-c++@ncar.ucar.edu
FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Re: Article for comp.std.c++: Eliminating #ifdef: if const
Author: mtr
Date: Tue, 20 Feb 1996 15:44
Date: Tue, 20 Feb 1996 15:44
72 lines
2698 bytes
2698 bytes
Shankar Unni (shankar@engr.sgi.com) wrote:
>No dice.
>
>Often, an #ifdef covers just a small part of an expression that may be
>different between different environments, or some such small differences:
>
> if (some condition) {
>#ifdef SOMEIMPL
> if (some other condition) {
>#endif /* SOMEIMPL */
> /* code */
> /* code */
> /* code */
>#ifdef SOMEIMPL
> }
>#endif /* SOMEIMPL */
> }
Personally I would be quite happy to see that style of #ifdef'ing
disappear. I've seen too much code rendered totally impenetrable by
just this technique. I would write the above as:
if (some condition) {
if const (SOMEIMPL) {
if (some other condition)
code();
}
else const {
code();
}
}
where code() is the code wrapped up in a (possibly inline) function.
Alternatively, if you can persuade your compiler not to complain about
a constant if() controlling expression:
if (some condition) {
bool doit;
if const (SOMEIMPL) {
doit = some other condition;
}
else const {
doit = true;
}
if (doit) {
code
}
}
Of course in reality you would hope to bury all the implementation
dependent stuff behind a portability layer.
>Also, the #ifdefs serve a purpose in pointing out the fact that this piece
>of code is system-dependent. The syntax you propose hides its warts rather
>too well, and make it easy for a reader to miss the significant piece of
>information that this area of code is system-dependent.
I agree that this is a problem, but I would argue that sprinkling `if
const' (or #ifdef) throughout the main body of the code is bad style,
and thus comes under the `any feature can be misused' getout. Misuse
like this is easily spotted: `if const' is just as visible to grep as #if.
Mark
[ To submit articles: Try just posting with your newsreader. If that fails,
use mailto:std-c++@ncar.ucar.edu
FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Re: Article for comp.std.c++: Eliminating #ifdef: if const
Author: Tony Cook
Date: Tue, 20 Feb 1996 18:48
Date: Tue, 20 Feb 1996 18:48
84 lines
3564 bytes
3564 bytes
Mark Russell (M.T.Russell@ukc.ac.uk) wrote:
: Subject: Eliminating #ifdef: if const
: Here's an idea I had for a non-preprocessor replacement for #if and #ifdef.
: if const (<expr>) { <stuff> }
: `if const' is a compile time version of `if'. <expr> is a constant
: expression which is convertible to bool. If it yields true, <stuff>
: is processed as normal. Otherwise <stuff> is parsed into tokens, but
: ignored except for counting { and } nesting. <stuff> is anything that
: can appear inside a namespace block. `if const' does not introduce a
: new scope.
: The following is also legal, with the obvious meaning:
: if const (<expr>) { <stuff> } else const { <other stuff> }
: There are also a number of compile-time pseudo-functions (I hesitate
: to call them pragmas):
: bool #os_version(const char* str)
: os version (uname -r) at or later than str
: bool #os_name(const char *str)
: os name (uname -s) is str
These would require mechanisms to supply operating system parameters
to the compiler - besides, a module compiled for one operating
system can sometimes be linked into an executable for another on
(some 16-bit DOS modules can be used in a Windows program).
OS/2 FAPI programs can run under DOS, OS/2 or Windows NT.
: bool #compiler_name(const char *)
: bool #compiler_version(const char*)
: Same tests for the compiler
These might be nice.
: Using these you could do things like this:
: // Are we running IRIX 5.3
: const bool using_irix_53 = #os_name("IRIX") &&
: #os_version("5.3") && !#os_version("5.4")
: if const (using_irix_53) {
: // Do some stuff needed just for IRIX 5.3
: }
: if const (#compiler("g++")) {
: // Do some g++ stuff
: }
: if const (#header_exists("sys/frobnitz9000.h")) {
: #include "sys/frobnitz9000.h"
: // Do stuff for the Frobnitz 9000
: }
Doesn't this bind the preprocess and compiler closer together? For
the compilation stages in the WP won't the #include occur in stage 4
and the if const in stage 7?
: With this I could personally stop using the preprocessor for anything
: except #include. If `include' (as described in D&E) is also
: implemented, I could stop using the preprocessor altogether, which
: would be nice.
What's the difference between what you've specified and the
preprocessor (other than different syntax?)
--
Tony Cook - tony@online.tmx.com.au
100237.3425@compuserve.com
---
[ To submit articles: Try just posting with your newsreader. If that fails,
use mailto:std-c++@ncar.ucar.edu
FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
Comments? mailto:std.c++-request@ncar.ucar.edu
]
Re: Article for comp.std.c++: Eliminating #ifdef: if const
Author: Fergus Henderson
Date: Thu, 22 Feb 1996 20:20
Date: Thu, 22 Feb 1996 20:20
73 lines
2853 bytes
2853 bytes
shankar@mti.mti.sgi.com (Shankar Unni) writes:
>Often, an #ifdef covers just a small part of an expression that may be
>different between different environments, or some such small differences:
>
> if (some condition) {
>#ifdef SOMEIMPL
> if (some other condition) {
>#endif /* SOMEIMPL */
> /* code */
> /* code */
> /* code */
>#ifdef SOMEIMPL
> }
>#endif /* SOMEIMPL */
> }
But with `if const', your 11 lines of code could be rewritten as either
if (some condition) {
if (SOMEIMPL && some other condition) {
/* code */
/* code */
/* code */
}
}
(7 lines of code)
or, if `some other condition' won't compile on other implementations, as
if (some condition) {
bool some_other_condition = true;
if const (SOMEIMPL) {
some_other_condition = some other condition;
}
if (other_condition) {
/* code */
/* code */
/* code */
}
}
(11 lines of code)
Both of these solutions have the advantage that the test for `SOMEIMPL'
occurs only once, so things will be easier if you later have to change it to
`SOMEIMPL || SOMEOTHERIMPL'.
>Duplicating all the code so that each half is precisely correct in its {}
>matching is both tedious and error-prone (trying to verify that both parts
>of the expression are fixed).
But fortunately as shown above it would not be required.
>Also, the #ifdefs serve a purpose in pointing out the fact that this piece
>of code is system-dependent. The syntax you propose hides its warts rather
>too well, and make it easy for a reader to miss the significant piece of
>information that this area of code is system-dependent.
True, but a convention of using upper-case for SOMEIMPL and similar constants
would make such tests stand out.
--
Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3
---
[ To submit articles: try just posting with your news-reader.
If that fails, use mailto:std-c++@ncar.ucar.edu
FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu.
]
Re: Article for comp.std.c++: Eliminating #ifdef: if const
Author: Martin J. Maney
Date: Fri, 23 Feb 1996 15:55
Date: Fri, 23 Feb 1996 15:55
91 lines
4198 bytes
4198 bytes
Fergus Henderson (fjh@munta.cs.mu.OZ.AU) wrote:
> shankar@mti.mti.sgi.com (Shankar Unni) writes:
> >Often, an #ifdef covers just a small part of an expression that may be
> >different between different environments, or some such small differences:
> >
> > if (some condition) {
> >#ifdef SOMEIMPL
> > if (some other condition) {
> >#endif /* SOMEIMPL */
> > /* code */
> > /* code */
> > /* code */
> >#ifdef SOMEIMPL
> > }
> >#endif /* SOMEIMPL */
> > }
> But with `if const', your 11 lines of code could be rewritten as either
> if (some condition) {
> if (SOMEIMPL && some other condition) {
> /* code */
> /* code */
> /* code */
> }
> }
> (7 lines of code)
Of course it's a little unfair to pick on the specific features of the
example, but I can no longer resist the temptation to point out that all
of these are simply awful ways to deal with this sort of target
dependency. What you truly want in these cases is to replace the
platform-dependent hackery with
if (implementation_defined_test())
{
...
}
And let implementation_defined_test() be defined in whatever place you
like to collect portability [sic] stuff. In C one might have to choose
between a function-like macro that could be unsafe and a function that
might be too costly, but in C++ you can have hte best of both worlds if
you make it an inline function.
Again: I realize there are other applications for the proposed idea; I
encourage its supporters to present them and make a better case for this
feature. But this example strikes me as an argument _against_ the
feature on the grounds that it encourages what I am happy to call a
simply awful coding style.
> Both of these solutions have the advantage that the test for `SOMEIMPL'
> occurs only once, so things will be easier if you later have to change it to
> `SOMEIMPL || SOMEOTHERIMPL'.
Ditto. Plus the advantage that if this condition is tested for elsewhere
- and if it isn't now, what are the odds it will be before the program is
finally retired from service? - the inline function, like the ugly C
macro, will at least have a chance of getting the change into every piece
of code that uses it, if only the dependencies are setup correctly. ;-)
> >Duplicating all the code so that each half is precisely correct in its {}
> >matching is both tedious and error-prone (trying to verify that both parts
> >of the expression are fixed).
> But fortunately as shown above it would not be required.
Ditto.
> >Also, the #ifdefs serve a purpose in pointing out the fact that this piece
> >of code is system-dependent. The syntax you propose hides its warts rather
> >too well, and make it easy for a reader to miss the significant piece of
> >information that this area of code is system-dependent.
> True, but a convention of using upper-case for SOMEIMPL and similar constants
> would make such tests stand out.
I will concede that the inline function hides this as well as you want to
- I used a long, blatant name in my example for precisely this reason.
But then again, if you don't have to worry about writing the details of
the target-dependent code all over the place, what difference does it make
how visible it is or isn't in use?
[ To submit articles: Try just posting with your newsreader.
If that fails, use mailto:std-c++@ncar.ucar.edu
FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads