www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Question about version ( ) keyword

reply Vincent R <lol dlang.org> writes:
Hi,

When looking at core definitions like core.sys.posix.pthread I 
can see some "duplicated" code because it seems version doesn't 
support Or as we would do in C/C++ with #ifdefined.
For instance if can read this:

version( CRuntime_Glibc )
{
     enum PTHREAD_BARRIER_SERIAL_THREAD = -1;

     int pthread_barrier_destroy(pthread_barrier_t*);
     int pthread_barrier_init(pthread_barrier_t*, in 
pthread_barrierattr_t*, uint);
     int pthread_barrier_wait(pthread_barrier_t*);
     int pthread_barrierattr_destroy(pthread_barrierattr_t*);
     int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, 
int*);
     int pthread_barrierattr_init(pthread_barrierattr_t*);
     int pthread_barrierattr_setpshared(pthread_barrierattr_t*, 
int);
}
else version( FreeBSD )
{
     enum PTHREAD_BARRIER_SERIAL_THREAD = -1;

     int pthread_barrier_destroy(pthread_barrier_t*);
     int pthread_barrier_init(pthread_barrier_t*, in 
pthread_barrierattr_t*, uint);
     int pthread_barrier_wait(pthread_barrier_t*);
     int pthread_barrierattr_destroy(pthread_barrierattr_t*);
     int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, 
int*);
     int pthread_barrierattr_init(pthread_barrierattr_t*);
     int pthread_barrierattr_setpshared(pthread_barrierattr_t*, 
int);
}
else version (OSX)
{
}
else version (Solaris)
{
     enum PTHREAD_BARRIER_SERIAL_THREAD = -2;

     int pthread_barrier_destroy(pthread_barrier_t*);
     int pthread_barrier_init(pthread_barrier_t*, in 
pthread_barrierattr_t*, uint);
     int pthread_barrier_wait(pthread_barrier_t*);
     int pthread_barrierattr_destroy(pthread_barrierattr_t*);
     int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, 
int*);
     int pthread_barrierattr_init(pthread_barrierattr_t*);
     int pthread_barrierattr_setpshared(pthread_barrierattr_t*, 
int);
}
else version (CRuntime_Bionic)
{
}
else
{
     static assert(false, "Unsupported platform");
}

When I see this code I cannot help thinking of something like:

version( CRuntime_Glibc ) || version( FreeBSD ) || version 
(Solaris)
{
     if(version(Solaris))
	   enum PTHREAD_BARRIER_SERIAL_THREAD = -2;
	else
	   enum PTHREAD_BARRIER_SERIAL_THREAD = -1;
	
     int pthread_barrier_destroy(pthread_barrier_t*);
     int pthread_barrier_init(pthread_barrier_t*, in 
pthread_barrierattr_t*, uint);
     int pthread_barrier_wait(pthread_barrier_t*);
     int pthread_barrierattr_destroy(pthread_barrierattr_t*);
     int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, 
int*);
     int pthread_barrierattr_init(pthread_barrierattr_t*);
     int pthread_barrierattr_setpshared(pthread_barrierattr_t*, 
int);
}
else version (OSX) ||version (CRuntime_Bionic)
{
}
else
{
     static assert(false, "Unsupported platform");
}

I suppose language creators had good reasons to not allow it but 
I am a bit disapointed by the aspect of this language because 
some files are really verbose.
However I understand that this limitation allow a clear 
separation between different platforms...
Mar 21 2016
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 21 March 2016 at 14:51:48 UTC, Vincent R wrote:
 However I understand that this limitation allow a clear 
 separation between different platforms...
That's exactly why it is done this way, so the platforms are clearly separated from each other and always grouped together for themselves. When writing these, we try to copy/paste it from the specific platform's documentation as a whole block so it is there and correct without accidentally assuming a Linux function is the same as a FreeBSD function (for example) just because a few of them were and got grouped in an OR block, but the rest weren't and got overlooked. Doing it separately makes sure we look each thing up for the specific platform to get it right. (Version does not support an or thing itself to force this, but still if you really wanted to, you can static if or set shared version identifiers, so it is possible, just the language and library guidelines don't want you doing it that way.)
Mar 21 2016
parent Chris Wright <dhasenan gmail.com> writes:
On Mon, 21 Mar 2016 15:01:27 +0000, Adam D. Ruppe wrote:

 On Monday, 21 March 2016 at 14:51:48 UTC, Vincent R wrote:
 However I understand that this limitation allow a clear separation
 between different platforms...
That's exactly why it is done this way, so the platforms are clearly separated from each other and always grouped together for themselves. When writing these, we try to copy/paste it from the specific platform's documentation as a whole block
That works where you are importing platform APIs. version(Posix) makes that a bit easier in some cases. And the general tactic is to wrap those APIs to be not platform-specific so you can omit version statements almost everywhere. But if you still find that you have things that need to be versioned out but much of the code is identical, another option is to use mixins: template DeclarationsForiOSAndAndroid() { extern(C) void foo(); extern(C) int bar(int i); } version (iOS) { mixin DeclarationsForiOSAndAndroid; extern(C) int iOSVersion(); } version (Android) { mixin DeclarationsForiOSAndAndroid; extern(C) int androidVersion(); } There will rarely be a reason to do this, but you might find it handy some day.
Mar 22 2016
prev sibling next sibling parent Joakim <dlang joakim.fea.st> writes:
On Monday, 21 March 2016 at 14:51:48 UTC, Vincent R wrote:
 Hi,

 When looking at core definitions like core.sys.posix.pthread I 
 can see some "duplicated" code because it seems version doesn't 
 support Or as we would do in C/C++ with #ifdefined.
 For instance if can read this:

 [...]
The language creator is against it, more info can be found in forum threads like this one: http://forum.dlang.org/thread/n0u5v3$1lsh$1 digitalmars.com
Mar 21 2016
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
On Monday, 21 March 2016 at 14:51:48 UTC, Vincent R wrote:
 When I see this code I cannot help thinking of something like:

 version( CRuntime_Glibc ) || version( FreeBSD ) || version 
 (Solaris)
 {
     if(version(Solaris))
 	   enum PTHREAD_BARRIER_SERIAL_THREAD = -2;
 	else
 	   enum PTHREAD_BARRIER_SERIAL_THREAD = -1;
 	
     int pthread_barrier_destroy(pthread_barrier_t*);
     int pthread_barrier_init(pthread_barrier_t*, in 
 pthread_barrierattr_t*, uint);
     int pthread_barrier_wait(pthread_barrier_t*);
     int pthread_barrierattr_destroy(pthread_barrierattr_t*);
     int pthread_barrierattr_getpshared(in 
 pthread_barrierattr_t*, int*);
     int pthread_barrierattr_init(pthread_barrierattr_t*);
     int pthread_barrierattr_setpshared(pthread_barrierattr_t*, 
 int);
 }
 else version (OSX) ||version (CRuntime_Bionic)
 {
 }
 else
 {
     static assert(false, "Unsupported platform");
 }
Even shorter: version(Solaris) enum PTHREAD_BARRIER_SERIAL_THREAD = -2; else enum PTHREAD_BARRIER_SERIAL_THREAD = -1; int pthread_barrier_destroy(pthread_barrier_t*); int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint); int pthread_barrier_wait(pthread_barrier_t*); int pthread_barrierattr_destroy(pthread_barrierattr_t*); int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*); int pthread_barrierattr_init(pthread_barrierattr_t*); int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
Mar 21 2016
parent Daniel Kozak via Digitalmars-d <digitalmars-d puremagic.com> writes:
Dne 21.3.2016 v 18:18 Kagamin via Digitalmars-d napsal(a):
 On Monday, 21 March 2016 at 14:51:48 UTC, Vincent R wrote:
 When I see this code I cannot help thinking of something like:

 version( CRuntime_Glibc ) || version( FreeBSD ) || version (Solaris)
 {
     if(version(Solaris))
        enum PTHREAD_BARRIER_SERIAL_THREAD = -2;
     else
        enum PTHREAD_BARRIER_SERIAL_THREAD = -1;

     int pthread_barrier_destroy(pthread_barrier_t*);
     int pthread_barrier_init(pthread_barrier_t*, in 
 pthread_barrierattr_t*, uint);
     int pthread_barrier_wait(pthread_barrier_t*);
     int pthread_barrierattr_destroy(pthread_barrierattr_t*);
     int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
     int pthread_barrierattr_init(pthread_barrierattr_t*);
     int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
 }
 else version (OSX) ||version (CRuntime_Bionic)
 {
 }
 else
 {
     static assert(false, "Unsupported platform");
 }
Even shorter: version(Solaris) enum PTHREAD_BARRIER_SERIAL_THREAD = -2; else enum PTHREAD_BARRIER_SERIAL_THREAD = -1; int pthread_barrier_destroy(pthread_barrier_t*); int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint); int pthread_barrier_wait(pthread_barrier_t*); int pthread_barrierattr_destroy(pthread_barrierattr_t*); int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*); int pthread_barrierattr_init(pthread_barrierattr_t*); int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
I do not see: static assert(false, "Unsupported platform"); so no, it is not shorter just wrong ;-)
Mar 21 2016
prev sibling next sibling parent Daniel Kozak via Digitalmars-d <digitalmars-d puremagic.com> writes:
Dne 21.3.2016 v 15:51 Vincent R via Digitalmars-d napsal(a):
 Hi,

 When looking at core definitions like core.sys.posix.pthread I can see 
 some "duplicated" code because it seems version doesn't support Or as 
 we would do in C/C++ with #ifdefined.
 For instance if can read this:

 version( CRuntime_Glibc )
 {
     enum PTHREAD_BARRIER_SERIAL_THREAD = -1;

     int pthread_barrier_destroy(pthread_barrier_t*);
     int pthread_barrier_init(pthread_barrier_t*, in 
 pthread_barrierattr_t*, uint);
     int pthread_barrier_wait(pthread_barrier_t*);
     int pthread_barrierattr_destroy(pthread_barrierattr_t*);
     int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
     int pthread_barrierattr_init(pthread_barrierattr_t*);
     int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
 }
 else version( FreeBSD )
 {
     enum PTHREAD_BARRIER_SERIAL_THREAD = -1;

     int pthread_barrier_destroy(pthread_barrier_t*);
     int pthread_barrier_init(pthread_barrier_t*, in 
 pthread_barrierattr_t*, uint);
     int pthread_barrier_wait(pthread_barrier_t*);
     int pthread_barrierattr_destroy(pthread_barrierattr_t*);
     int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
     int pthread_barrierattr_init(pthread_barrierattr_t*);
     int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
 }
 else version (OSX)
 {
 }
 else version (Solaris)
 {
     enum PTHREAD_BARRIER_SERIAL_THREAD = -2;

     int pthread_barrier_destroy(pthread_barrier_t*);
     int pthread_barrier_init(pthread_barrier_t*, in 
 pthread_barrierattr_t*, uint);
     int pthread_barrier_wait(pthread_barrier_t*);
     int pthread_barrierattr_destroy(pthread_barrierattr_t*);
     int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
     int pthread_barrierattr_init(pthread_barrierattr_t*);
     int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
 }
 else version (CRuntime_Bionic)
 {
 }
 else
 {
     static assert(false, "Unsupported platform");
 }

 When I see this code I cannot help thinking of something like:

 version( CRuntime_Glibc ) || version( FreeBSD ) || version (Solaris)
 {
     if(version(Solaris))
        enum PTHREAD_BARRIER_SERIAL_THREAD = -2;
     else
        enum PTHREAD_BARRIER_SERIAL_THREAD = -1;

     int pthread_barrier_destroy(pthread_barrier_t*);
     int pthread_barrier_init(pthread_barrier_t*, in 
 pthread_barrierattr_t*, uint);
     int pthread_barrier_wait(pthread_barrier_t*);
     int pthread_barrierattr_destroy(pthread_barrierattr_t*);
     int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*);
     int pthread_barrierattr_init(pthread_barrierattr_t*);
     int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int);
 }
 else version (OSX) ||version (CRuntime_Bionic)
 {
 }
 else
 {
     static assert(false, "Unsupported platform");
 }

 I suppose language creators had good reasons to not allow it but I am 
 a bit disapointed by the aspect of this language because some files 
 are really verbose.
 However I understand that this limitation allow a clear separation 
 between different platforms...
It is already has been sad why this does not work. But you can still do something like this (or maybe even something better(shorter)): version(CRuntime_Glibc) { enum PTHREAD_BARRIER_SERIAL_THREAD = -1; version = WhatEver1; } else version(FreeBSD) { enum PTHREAD_BARRIER_SERIAL_THREAD = -1; version = WhatEver1; } else version (OSX) { version = WhatEver2; } else version (Solaris) { enum PTHREAD_BARRIER_SERIAL_THREAD = -2; version = WhatEver1; } else version (CRuntime_Bionic) { version = WhatEver2; } version (WhatEver1) { int pthread_barrier_destroy(pthread_barrier_t*); int pthread_barrier_init(pthread_barrier_t*, in pthread_barrierattr_t*, uint); int pthread_barrier_wait(pthread_barrier_t*); int pthread_barrierattr_destroy(pthread_barrierattr_t*); int pthread_barrierattr_getpshared(in pthread_barrierattr_t*, int*); int pthread_barrierattr_init(pthread_barrierattr_t*); int pthread_barrierattr_setpshared(pthread_barrierattr_t*, int); } else version (WhatEver2) else { static assert(false, "Unsupported platform"); } But to be fair I still prefer original code because it is obvious, which platform support what :)
Mar 21 2016
prev sibling parent Nick Treleaven <ntrel-pub mybtinternet.com> writes:
On Monday, 21 March 2016 at 14:51:48 UTC, Vincent R wrote:
 version( CRuntime_Glibc ) || version( FreeBSD ) || version 
 (Solaris)
 {
As a workaround, you can do it with static if and version strings: http://forum.dlang.org/post/op.vkshabecot0hzo las-miodowy
Mar 23 2016