DMD 1.005 release

Walter Bright newshound at digitalmars.com
Wed Feb 7 11:16:06 PST 2007


BCS wrote:
> Walter Bright wrote:
>> The right way to do versions that cut across multiple files is to 
>> abstract the versioning into an API, and implement the different 
>> versions in different modules.
> What about cases where 90% of the code is identical but small bits and 
> peaces are different? If I understand correctly, to do what you suggest 
> would requirer that those bits be put in functions and have several 
> versions of the function somewhere else. This could be a problem in 
> several ways
> 
> ===Tiny bits of code would requirer tiny functions that would hide what 
> is going on.

Yes, it would require tiny functions, though I don't agree they hide 
what is going on. Presumably a descriptive name would be used for it. 
One of the nice things about it is that porting the code requires 
generating a new module with the right implementations in it, which is a 
lot easier than going through checking all the #ifdef's (yes, I know one 
shouldn't have to do that, but in practice you ALWAYS have to because 
the macros always get misapplied, and often get forgotten to even 
apply). With an API, it is difficult to forget to use it, and difficult 
to use the wrong macro.

For example, when writing portable C code, one is often faced with the 
macros:
	__GNUC__	for the Gnu compiler
	linux		for the host operating system
	TARGET_LINUX	for the target operating system we're cross compiling for

I can't even count the number of times __GNUC__ was being used to decide 
whether we're compiling for windows or linux, or the host operating 
system was confused with the target:

#if __GNUC__
#include <pthreads.h>
#else
#include <windows.h>
#endif

AAAARRRRRGGGGGHHHHH!!! That, my friends, is evil.

Now, if one abstracted away what one was *doing* with threads, then one 
just does:

import mythreadapi;

and provide a different implementation of mythreadapi for windows or 
linux. It's a LOT harder to screw that up.

> version(RowMajor)
>     x = table[i][j];
> else // RowMinor
>     x = table[j][i];

int GetRow(i,j) { return table[i][j]; }

The function gets inlined.

> ====Empty else cases would result in do nothing functions:
> 
> version(StrongChecks)
> {
>     if(foo) ...
>     if(bar) ...
>     ...
> }
> //empty else
> 
> ====You can't break across function calls
> 
> switch(i)
> {
>     case 1:
>         version(Baz)
>             if(baz) break;
>         else
>             break;
>     case 2:
> 
>     ...// lots of un versioned code
> }

	if (globalversion.baz && baz)
		break;

> ====lots of version combinations
> 
> version(Foo) i = foo(i);
> version(Boo) i = boo(i);
> version(Fig) i = fig(i);
> version(Baz) i = baz(i);
> version(Bar) i = bar(i);    //32 options???

i = abc(i);	// a different abc is implemented for each version.

> 
> Are these valid concerns? Am I misunderstanding what you said?

They are valid concerns, you're just used to thinking in terms of the C 
preprocessor.



More information about the Digitalmars-d-announce mailing list