Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
January 07, 2005 no-preprocessor shortcoming? "function" macros at global scope | ||||
---|---|---|---|---|
| ||||
Attachments:
| Here's something that doesn't seem to be very simple or possible in D - "function" macros which can be used at the global scope, unlike regular functions which can't be. Take the following macros in COM and directx: #define MAKE_HRESULT(sev,fac,code) \ ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) #define _FACD3D 0x876 #define MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ) #define D3DERR_WRONGTEXTUREFORMAT MAKE_D3DHRESULT(2072) This defines a constant, D3DERR_WRONGTEXTUREFORMAT with some complicated value that you'd normally not be able to come up with without help from the macros. Converting to D, however, leaves you with: HRESULT MAKE_HRESULT(int sev, int fac, int code) { return (sev << 31) | (fac << 16) | code; } HRESULT MAKE_D3DHRESULT(int code) { return MAKE_HRESULT(1, _FACD3D, code); const HRESULT D3DERR_WRONGTEXTUREFORMAT=MAKE_D3DHRESULT(2072); Which, at global scope, of course gives you an error about it not being a constant expression. You can't call functions at global scope. I've tried doing this with a mixin, but it doesn't seem possible to define a variable with a mixed-in name within a mixin. Of course, it would be possible to run the original C++ file through the preprocessor to get the big ugly error codes, but this still doesn't solve the overall problem. |
January 07, 2005 Re: no-preprocessor shortcoming? "function" macros at global scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | On Thu, 6 Jan 2005 21:00:32 -0500, Jarrett Billingsley wrote: > Here's something that doesn't seem to be very simple or possible in D - "function" macros which can be used at the global scope, unlike regular functions which can't be. > > Take the following macros in COM and directx: > > #define MAKE_HRESULT(sev,fac,code) \ > ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) > #define _FACD3D 0x876 > #define MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ) > #define D3DERR_WRONGTEXTUREFORMAT MAKE_D3DHRESULT(2072) > > This defines a constant, D3DERR_WRONGTEXTUREFORMAT with some complicated value that you'd normally not be able to come up with without help from the macros. > > Converting to D, however, leaves you with: > > HRESULT MAKE_HRESULT(int sev, int fac, int code) { return (sev << 31) | (fac << 16) | code; } > HRESULT MAKE_D3DHRESULT(int code) { return MAKE_HRESULT(1, _FACD3D, code); > const HRESULT D3DERR_WRONGTEXTUREFORMAT=MAKE_D3DHRESULT(2072); > > Which, at global scope, of course gives you an error about it not being a constant expression. You can't call functions at global scope. > > I've tried doing this with a mixin, but it doesn't seem possible to define a variable with a mixed-in name within a mixin. > > Of course, it would be possible to run the original C++ file through the preprocessor to get the big ugly error codes, but this still doesn't solve the overall problem. Have you considered using the module constructor to create these 'constants' at runtime prior to main() getting control. Otherwise you might try ... import std.stdio; alias uint HRESULT; const uint _FACD3D = 0x876; const HRESULT D3DERR_WRONGTEXTUREFORMAT = (1 << 31)|(_FACD3D << 16)|2072; void main() { writefln("0x%08x", D3DERR_WRONGTEXTUREFORMAT); } -- Derek Melbourne, Australia 7/01/2005 2:56:24 PM |
January 07, 2005 Re: no-preprocessor shortcoming? "function" macros at global scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | On Fri, 7 Jan 2005 15:04:37 +1100, Derek Parnell wrote: > On Thu, 6 Jan 2005 21:00:32 -0500, Jarrett Billingsley wrote: > >> Here's something that doesn't seem to be very simple or possible in D - "function" macros which can be used at the global scope, unlike regular functions which can't be. >> >> Take the following macros in COM and directx: >> >> #define MAKE_HRESULT(sev,fac,code) \ >> ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) >> #define _FACD3D 0x876 >> #define MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ) >> #define D3DERR_WRONGTEXTUREFORMAT MAKE_D3DHRESULT(2072) >> >> This defines a constant, D3DERR_WRONGTEXTUREFORMAT with some complicated value that you'd normally not be able to come up with without help from the macros. >> >> Converting to D, however, leaves you with: >> >> HRESULT MAKE_HRESULT(int sev, int fac, int code) { return (sev << 31) | (fac << 16) | code; } >> HRESULT MAKE_D3DHRESULT(int code) { return MAKE_HRESULT(1, _FACD3D, code); >> const HRESULT D3DERR_WRONGTEXTUREFORMAT=MAKE_D3DHRESULT(2072); >> >> Which, at global scope, of course gives you an error about it not being a constant expression. You can't call functions at global scope. >> >> I've tried doing this with a mixin, but it doesn't seem possible to define a variable with a mixed-in name within a mixin. >> >> Of course, it would be possible to run the original C++ file through the preprocessor to get the big ugly error codes, but this still doesn't solve the overall problem. Yes, it would be useful to be able to do this (or similar) ... template mr(alias nam, alias sev, alias fac, alias code) { const HRESULT nam = (sev << 31) | (fac << 16) | code; } mixin mr!(D3DERR_WRONGTEXTUREFORMAT, 1, _FACD3D, 2072); -- Derek Melbourne, Australia 7/01/2005 3:55:42 PM |
January 07, 2005 Re: no-preprocessor shortcoming? "function" macros at global scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | On Thu, 6 Jan 2005 21:00:32 -0500, Jarrett Billingsley <kb3ctd2@yahoo.com> wrote: > Here's something that doesn't seem to be very simple or possible in D - "function" macros which can be used at the global scope, unlike regular functions which can't be. > > Take the following macros in COM and directx: > > #define MAKE_HRESULT(sev,fac,code) \ > ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) > #define _FACD3D 0x876 > #define MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ) > #define D3DERR_WRONGTEXTUREFORMAT MAKE_D3DHRESULT(2072) > > This defines a constant, D3DERR_WRONGTEXTUREFORMAT with some complicated value that you'd normally not be able to come up with without help from the macros. > > Converting to D, however, leaves you with: > > HRESULT MAKE_HRESULT(int sev, int fac, int code) { return (sev << 31) | (fac << 16) | code; } > HRESULT MAKE_D3DHRESULT(int code) { return MAKE_HRESULT(1, _FACD3D, code); > const HRESULT D3DERR_WRONGTEXTUREFORMAT=MAKE_D3DHRESULT(2072); > > Which, at global scope, of course gives you an error about it not being a constant expression. You can't call functions at global scope. > > I've tried doing this with a mixin, but it doesn't seem possible to define a variable with a mixed-in name within a mixin. > > Of course, it would be possible to run the original C++ file through the preprocessor to get the big ugly error codes, but this still doesn't solve the overall problem. > from http://www.digitalmars.com/d/template.html : " Recursive Templates Template features can be combined to produce some interesting effects, such as compile time evaluation of non-trivial functions. For example, a factorial template can be written: template factorial(int n : 1) { enum { factorial = 1 } } template factorial(int n) { // Note . used to find global template rather than enum enum { factorial = n* .factorial!(n-1) } } void test() { printf("%d\n", factorial!(4));// prints 24 } " Thus, your macros would be similar to: template MAKE_HRESULT(ulong sev, ulong fac, ulong code) { return cast(HRESULT)(sev<<31 | (fac<<16 | code)); } const int _FACD3D = 0x876; alias MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ); alias D3DERR_WRONGTEXTUREFORMAT MAKE_D3DHRESULT(2072); (not having anything to test it with makes it a bit difficult to check, but this should be close) -- "Yes, the american troops have advanced further. This will only make it easier for us to defeat them" - Iraqi Information Minister Muhammed Saeed al-Sahaf |
January 08, 2005 Re: no-preprocessor shortcoming? "function" macros at global scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simon Buchan | > template MAKE_HRESULT(ulong sev, ulong fac, ulong code) { > return cast(HRESULT)(sev<<31 | (fac<<16 | code)); > } > > const int _FACD3D = 0x876; > alias MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ); > alias D3DERR_WRONGTEXTUREFORMAT MAKE_D3DHRESULT(2072); There are a few problems with this snippet - one, the template isn't really a template (and doesn't have to be - it can just be a function). Second, the "alias MAKE_D3DHRESULT" line is illegal - alias doesn't give you quite the same functionality as #define. So, good effort, but I'm afraid it doesn't help much. |
January 08, 2005 Re: no-preprocessor shortcoming? "function" macros at global scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | > Have you considered using the module constructor to create these 'constants' at runtime prior to main() getting control. If I defined them in the module constructor, would they be at global scope? I would imagine not, but is there some kind of exception to the rule? > const uint _FACD3D = 0x876; > const HRESULT D3DERR_WRONGTEXTUREFORMAT = (1 << 31)|(_FACD3D << 16)|2072; Well this certainly works, but it kind of loses the ease with which a macro would be used. |
January 09, 2005 Re: no-preprocessor shortcoming? "function" macros at global scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simon Buchan | Simon Buchan wrote:
> Thus, your macros would be similar to:
> template MAKE_HRESULT(ulong sev, ulong fac, ulong code) {
> return cast(HRESULT)(sev<<31 | (fac<<16 | code));
> }
>
> const int _FACD3D = 0x876;
> alias MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code );
> alias D3DERR_WRONGTEXTUREFORMAT MAKE_D3DHRESULT(2072);
>
> (not having anything to test it with makes it a bit difficult to check,
> but this should be close)
Not quite, but the principle is quite sound. This should work. (however I am also too lazy to test!)
const ulong _FACD3D = 0x876;
template MAKE_HRESULT(ulong sev, ulong fac, ulong code) {
const ulong MAKE_HRESULT = (sev << 31) | (fac << 16) | code;
}
template MAKE_D3DHRESULT(ulong code) {
const ulong MAKE_D3DHRESULT = MAKE_HRESULT!(1, _FACD3D, code);
}
const int D3DERR_WRONGTEXTUREFORMAT = MAKE_D3DHRESULT!(2072);
-- andy
|
January 10, 2005 Re: no-preprocessor shortcoming? "function" macros at global scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andy Friesen | Well, that works great Andy! Had to make a few changes to make it work with HRESULTs as they are technically ints and not ulongs, so here's the revised version: template MAKE_HRESULT(uint sev, uint fac, uint code) { const HRESULT MAKE_HRESULT = cast(HRESULT)((sev << 31) | (fac << 16) | code); } template MAKE_D3DHRESULT(uint code) { const HRESULT MAKE_D3DHRESULT = MAKE_HRESULT!(1, _FACD3D, code); } const HRESULT D3DERR_WRONGTEXTUREFORMAT = MAKE_D3DHRESULT!(2072); I'm not real sure just HOW this works, but it does, so I'm not complaining. I dislike templates. |
January 13, 2005 Re: no-preprocessor shortcoming? "function" macros at global scope | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | On Mon, 10 Jan 2005 18:52:37 -0500, Jarrett Billingsley <kb3ctd2@yahoo.com> wrote: > Well, that works great Andy! Had to make a few changes to make it work with > HRESULTs as they are technically ints and not ulongs, so here's the revised > version: > > template MAKE_HRESULT(uint sev, uint fac, uint code) { > const HRESULT MAKE_HRESULT = cast(HRESULT)((sev << 31) | (fac << > 16) | code); > } > > template MAKE_D3DHRESULT(uint code) { > const HRESULT MAKE_D3DHRESULT = MAKE_HRESULT!(1, _FACD3D, code); > } > > const HRESULT D3DERR_WRONGTEXTUREFORMAT = MAKE_D3DHRESULT!(2072); > > I'm not real sure just HOW this works, but it does, so I'm not complaining. > I dislike templates. > > The idea here is that templates are like functions for the compiler, not the CPU (if that makes sense), just like macro's, only you can do funky recursive branching stuff with proper, developed, consistant syntax. About the only thing (Which is an incredibly ugly hack for namespacing, normally) that isn't covered is token concatination. -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/ |
Copyright © 1999-2021 by the D Language Foundation