🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

6 total messages Started by Mark Russell Fri, 16 Feb 1996 17:03
Article for comp.std.c++: Eliminating #ifdef: if const
#3441
Author: Mark Russell
Date: Fri, 16 Feb 1996 17:03
87 lines
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
#3345
Author: Shankar Unni
Date: Mon, 19 Feb 1996 23:16
52 lines
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
#3361
Author: mtr
Date: Tue, 20 Feb 1996 15:44
72 lines
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
#3384
Author: Tony Cook
Date: Tue, 20 Feb 1996 18:48
84 lines
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
#3408
Author: Fergus Henderson
Date: Thu, 22 Feb 1996 20:20
73 lines
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
#3419
Author: Martin J. Maney
Date: Fri, 23 Feb 1996 15:55
91 lines
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