digitalmars.D.learn - translate a macro to D
- teo (5/5) Jul 06 2011 What is the best way to translate following to D?
- Trass3r (4/9) Jul 06 2011 Just turn it into a function.
- teo (18/31) Jul 07 2011 Thank you. That did the trick.
- Trass3r (3/13) Jul 07 2011 You could just get rid of that extra macro and directly pass A.sizeof.
- teo (3/20) Jul 07 2011 ioctl types
- Steven Schveighoffer (17/47) Jul 07 2011 Well, I can't really say I understand the point of using this macro at
- teo (19/23) Jul 07 2011 Well, have a look please at ioctl.h (linux). You will find the following...
- Steven Schveighoffer (8/32) Jul 08 2011 Hm... I once wrote a D module that accessed a linux device driver (ipmi ...
- teo (26/69) Jul 11 2011 Steve,
- Steven Schveighoffer (37/89) Jul 11 2011 I think you may be confusing function templates with plain templates? I...
- teo (3/4) Jul 12 2011 Yes, I was a bit confused by the syntax, but I found that type of
What is the best way to translate following to D? #define MAKELONG(a, b) \ ((LONG) (((WORD) (a)) | ((DWORD) ((WORD) (b))) << 16)) The point is I would like to be able to use that at compile-time. The macro is supposed to define some constants.
Jul 06 2011
Am 06.07.2011, 16:15 Uhr, schrieb teo <teo.ubuntu yahoo.com>:What is the best way to translate following to D? #define MAKELONG(a, b) \ ((LONG) (((WORD) (a)) | ((DWORD) ((WORD) (b))) << 16)) The point is I would like to be able to use that at compile-time. The macro is supposed to define some constants.Just turn it into a function. If you assign it to an enum or use it as an initializer for global immutables it should be evaluated at compile-time.
Jul 06 2011
On Wed, 06 Jul 2011 16:21:31 +0200, Trass3r wrote:Am 06.07.2011, 16:15 Uhr, schrieb teo <teo.ubuntu yahoo.com>:Thank you. That did the trick. However I am facing another problem: There is a macro, which obtains the size of a type #define TYPESIZE(t) (sizeof(t)) Example: printf("%ld\n", TYPESIZE(short)); printf("%ld\n", TYPESIZE(struct A)); The TYPESIZE macro is used within another macro which defines constants. #define M(a,b,size) \ ((a) << SHIFT_A) | \ ((b) << SHIFT_B) | \ ((size) << SHIFT_SIZE)) #define MM(a,b,type) M((a),(b),(TYPESIZE(type))) Example: #define C1 MM(1, 2, struct A) #define C2 MM(3, 4, struct B) How can I translate that to D?What is the best way to translate following to D? #define MAKELONG(a, b) \ ((LONG) (((WORD) (a)) | ((DWORD) ((WORD) (b))) << 16)) The point is I would like to be able to use that at compile-time. The macro is supposed to define some constants.Just turn it into a function. If you assign it to an enum or use it as an initializer for global immutables it should be evaluated at compile-time.
Jul 07 2011
The TYPESIZE macro is used within another macro which defines constants. #define M(a,b,size) \ ((a) << SHIFT_A) | \ ((b) << SHIFT_B) | \ ((size) << SHIFT_SIZE)) #define MM(a,b,type) M((a),(b),(TYPESIZE(type))) Example: #define C1 MM(1, 2, struct A) #define C2 MM(3, 4, struct B) How can I translate that to D?You could just get rid of that extra macro and directly pass A.sizeof. Otherwise you need to use templates. Can't say more cause I can't imagine what the heck this code is used for.
Jul 07 2011
On Thu, 07 Jul 2011 17:54:40 +0200, Trass3r wrote:ioctl types BTW: there is no ioctl module within phobosThe TYPESIZE macro is used within another macro which defines constants. #define M(a,b,size) \ ((a) << SHIFT_A) | \ ((b) << SHIFT_B) | \ ((size) << SHIFT_SIZE)) #define MM(a,b,type) M((a),(b),(TYPESIZE(type))) Example: #define C1 MM(1, 2, struct A) #define C2 MM(3, 4, struct B) How can I translate that to D?You could just get rid of that extra macro and directly pass A.sizeof. Otherwise you need to use templates. Can't say more cause I can't imagine what the heck this code is used for.
Jul 07 2011
On Thu, 07 Jul 2011 11:38:05 -0400, teo <teo.ubuntu yahoo.com> wrote:On Wed, 06 Jul 2011 16:21:31 +0200, Trass3r wrote:Well, I can't really say I understand the point of using this macro at all. sizeof is a builtin, and part of the C spec. Why not just use sizeof? In d it's t.sizeof.Am 06.07.2011, 16:15 Uhr, schrieb teo <teo.ubuntu yahoo.com>:Thank you. That did the trick. However I am facing another problem: There is a macro, which obtains the size of a type #define TYPESIZE(t) (sizeof(t))What is the best way to translate following to D? #define MAKELONG(a, b) \ ((LONG) (((WORD) (a)) | ((DWORD) ((WORD) (b))) << 16)) The point is I would like to be able to use that at compile-time. The macro is supposed to define some constants.Just turn it into a function. If you assign it to an enum or use it as an initializer for global immutables it should be evaluated at compile-time.Example: printf("%ld\n", TYPESIZE(short)); printf("%ld\n", TYPESIZE(struct A));printf("%ld %ld\n", short.sizeof, A.sizeof);The TYPESIZE macro is used within another macro which defines constants. #define M(a,b,size) \ ((a) << SHIFT_A) | \ ((b) << SHIFT_B) | \ ((size) << SHIFT_SIZE)) #define MM(a,b,type) M((a),(b),(TYPESIZE(type)))Define MM and M as normal functions as Trass3r suggested, then use type.sizeof.Example: #define C1 MM(1, 2, struct A) #define C2 MM(3, 4, struct B)Note, in D, to ensure compile-time evaluation, it's useful to have a template that does this: template MM(uint a, uint b, T) { enum MM = (a << SHIFT_A) | (b << SHIFT_B) | (T.sizeof << SHIFT_SIZE); } Usage is like: enum C1 = MM!(1, 2, A); enum C2 = MM!(3, 4, B);
Jul 07 2011
On Thu, 07 Jul 2011 11:57:51 -0400, Steven Schveighoffer wrote:Well, I can't really say I understand the point of using this macro at all. sizeof is a builtin, and part of the C spec. Why not just use sizeof?Well, have a look please at ioctl.h (linux). You will find the following macros: #define _IOC(dir,type,nr,size) \ (((dir) << _IOC_DIRSHIFT) | \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) #define _IOC_TYPECHECK(t) (sizeof(t)) /* used to create numbers */ #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK (size))) #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr), (_IOC_TYPECHECK(size))) #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr), (_IOC_TYPECHECK(size))) This is what I am after. However I thought that a simplified case will make it easier to describe the problem.
Jul 07 2011
On Thu, 07 Jul 2011 16:23:33 -0400, teo <teo.ubuntu yahoo.com> wrote:On Thu, 07 Jul 2011 11:57:51 -0400, Steven Schveighoffer wrote:Hm... I once wrote a D module that accessed a linux device driver (ipmi driver to be specific). I did it in D1, and I used CTFE. For sure, t.sizeof should work instead of _IOC_TYPECHECK. But Linux supports a multitude of CPUs, perhaps other CPUs need a different macro for this. It's the only thing I can think of to explain having a specific macro to do sizeof. -SteveWell, I can't really say I understand the point of using this macro at all. sizeof is a builtin, and part of the C spec. Why not just use sizeof?Well, have a look please at ioctl.h (linux). You will find the following macros: #define _IOC(dir,type,nr,size) \ (((dir) << _IOC_DIRSHIFT) | \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) #define _IOC_TYPECHECK(t) (sizeof(t)) /* used to create numbers */ #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK (size))) #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr), (_IOC_TYPECHECK(size))) #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr), (_IOC_TYPECHECK(size))) This is what I am after. However I thought that a simplified case will make it easier to describe the problem.
Jul 08 2011
On Fri, 08 Jul 2011 09:54:40 -0400, Steven Schveighoffer wrote:On Thu, 07 Jul 2011 16:23:33 -0400, teo <teo.ubuntu yahoo.com> wrote:Steve, I translated those macros to regular functions and it works that way (using T.sizeof), however I could have used a function template instead as you suggested before and therefore I have a question: Are there any benefits of using function templates instead of regular functions in that particular case? The above leads me to another question: are those functions evaluated at compile-time? I suppose they are not. Here an example usage: uint _IOC(uint dir, uint type, uint nr, uint size) { return (dir << _IOC_DIRSHIFT) | (type << _IOC_TYPESHIFT) | (nr << _IOC_NRSHIFT) | (size << _IOC_SIZESHIFT); } uint _IO(uint type, uint nr) { return _IOC(_IOC_NONE, type, nr, 0); } uint _IOWR(uint type, uint nr, uint size) { return _IOC(_IOC_READ | _IOC_WRITE, type, nr, size); } In another module define the constants: const C1 = _IO(1, 2); const C2 = _IOWR(2, 3, A.sizeof);On Thu, 07 Jul 2011 11:57:51 -0400, Steven Schveighoffer wrote:Hm... I once wrote a D module that accessed a linux device driver (ipmi driver to be specific). I did it in D1, and I used CTFE. For sure, t.sizeof should work instead of _IOC_TYPECHECK. But Linux supports a multitude of CPUs, perhaps other CPUs need a different macro for this. It's the only thing I can think of to explain having a specific macro to do sizeof. -SteveWell, I can't really say I understand the point of using this macro at all. sizeof is a builtin, and part of the C spec. Why not just use sizeof?Well, have a look please at ioctl.h (linux). You will find the following macros: #define _IOC(dir,type,nr,size) \ (((dir) << _IOC_DIRSHIFT) | \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) #define _IOC_TYPECHECK(t) (sizeof(t)) /* used to create numbers */ #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK (size))) #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr), (_IOC_TYPECHECK(size))) #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr), (_IOC_TYPECHECK(size))) This is what I am after. However I thought that a simplified case will make it easier to describe the problem.
Jul 11 2011
On Mon, 11 Jul 2011 09:21:53 -0400, teo <teo.ubuntu yahoo.com> wrote:On Fri, 08 Jul 2011 09:54:40 -0400, Steven Schveighoffer wrote:I think you may be confusing function templates with plain templates? I remember suggesting this: template MM(uint a, uint b, T) { enum MM = (a << SHIFT_A) | (b << SHIFT_B) | (T.sizeof << SHIFT_SIZE); } which is *not* a function template, it's simply a template which evaluates to an enum. The advantage is, no matter where you use it, it is done at compile time. For something like ioctl constants, this is important. Let's take a simple example: myconstant(uint x) { return x << 5; } Now, if you use it in some code: ioctl(myconstant(2), ...); In a standard build (i.e. without any switches), the call to myconstant is made, and the shift is performed, even when the value is easily known at compile time. Essentially you have wasted cycles computing the myconstant result. If you have both optimization (-O) and inlining (-inline), this might result in the correct constant being sent to ioctl, but there is a better way... If we simply wrap myconstant into a template enum: template myconstantCT(uint x) { enum myconstantCT = myconstant(x); } myconstantCT is evaluated at compile time, and replace with the exact number wherever you use it. This happens regardless of compiler switches: ioctl(myconstantCT!2, ...) This always results in simply passing a number to ioctl. So the benefit of using a template enum to do parameterized constants is that it guarantees compile time evaluation. This is a perfect fit for IOCTL constants which never change. -SteveOn Thu, 07 Jul 2011 16:23:33 -0400, teo <teo.ubuntu yahoo.com> wrote:Steve, I translated those macros to regular functions and it works that way (using T.sizeof), however I could have used a function template instead as you suggested before and therefore I have a question: Are there any benefits of using function templates instead of regular functions in that particular case? The above leads me to another question: are those functions evaluated at compile-time? I suppose they are not.On Thu, 07 Jul 2011 11:57:51 -0400, Steven Schveighoffer wrote:Hm... I once wrote a D module that accessed a linux device driver (ipmi driver to be specific). I did it in D1, and I used CTFE. For sure, t.sizeof should work instead of _IOC_TYPECHECK. But Linux supports a multitude of CPUs, perhaps other CPUs need a different macro for this. It's the only thing I can think of to explain having a specific macro to do sizeof. -SteveWell, I can't really say I understand the point of using this macro at all. sizeof is a builtin, and part of the C spec. Why not just use sizeof?Well, have a look please at ioctl.h (linux). You will find the following macros: #define _IOC(dir,type,nr,size) \ (((dir) << _IOC_DIRSHIFT) | \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) #define _IOC_TYPECHECK(t) (sizeof(t)) /* used to create numbers */ #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK (size))) #define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr), (_IOC_TYPECHECK(size))) #define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr), (_IOC_TYPECHECK(size))) This is what I am after. However I thought that a simplified case will make it easier to describe the problem.
Jul 11 2011
I think you may be confusing function templates with plain templates?Yes, I was a bit confused by the syntax, but I found that type of templates on page 281 in TDPL. That is an eponymous template. Thanks.
Jul 12 2011