Great idea. I've had lots of problems wrangling versions.
I find a numeric version number in conjunction with a platform version and/or an architecture version too, are the most common logical combinations I encounter, and D version syntax makes it a pain.
I almost exclusively set some bools at the top and use static of throughout.
This is a nice alternative, opDispatch is clever :)

On 5 Jun 2013 20:34, "Timothee Cour" <thelastmammoth@gmail.com> wrote:
Actually I can improve syntax a bit as follows:


user code:
----
void main(){
static if(versions.OSX&& versions.D_NoBoundsChecks || !versions.has!"assert)
  writeln("special code");
}
----

(note the alternate syntax with 'has' to support special keyword versions such as assert).
The only drawback is that I'd like to have instead:
static if(versions.OSX&& versions.D_NoBoundsChecks || !versions["assert"] )
any idea to support that?

library code:
---
//in std.compiler
enum versions=(){
struct versions_{
bool has(alias a)(){
mixin(`
version(`~a~`){
return true;
}
else 
return false;
`);
}

alias has this;

auto opDispatch(string a)(){
mixin(`
version(`~a~`){
return true;
}
else 
return false;
`);
}
}
return versions_.init;
}();
---




On Wed, Jun 5, 2013 at 2:28 AM, Timothee Cour <thelastmammoth@gmail.com> wrote:
Just figured out we can do this. Could this be added to phobos?

----
//in std.compiler (or std.traits?)
template Version(alias V){
mixin(`
version(`~V~`){
enum Version=true;
}
else 
enum Version=false;
`);
}
----

usage:

----
import std.compiler;
void main(){
static if(!Version!"assert")
writeln("not assert");

static if(Version!"OSX" && !Version!"D_NoBoundsChecks" || !Version!"assert")
        {
writeln("special code");
}
}
----

without this, we have to resort to something ugly, not dry, error prone:

----
//pollutes namespace, as we can't define version=temp inside a function
version(OSX)
{
version(D_NoBoundsChecks)
        {
}
else
        {
version=temp;//need to make sure temp doesn't clash with other version identifiers / symbols
}
}
else
{
version(assert)
        {
}
else
        {
version=temp;//NOT DRY: repeats temp
}
}

void main()
{
version(assert)
        {
}
else
        {
writeln("not assert");
}

version(temp) // here we use it
        {
writeln("special code");
}
}
----


Likewise, with debug:
----
template Debug(alias V){
import std.traits:isIntegral;
static if(!isIntegral!(typeof(V))){
mixin(`
debug(`~V~`){
enum Debug=true;
}
else 
enum Debug=false;
`);
}
else{
import std.conv:to;
mixin(`
debug(`~V.to!string~`){
enum Debug=true;
}
else 
enum Debug=false;
`);
/+
//NOTE:maybe a dmd bug but this didn't work
debug(V)
   enum Debug=true;
else 
   enum Debug=false;
+/
}
}
----


usage:
----
void main(){
        import std.compiler;
static if(Debug!2){
writeln("debug>=2");
}
static if(Debug!"foo"){
writeln("debug=foo");
}
}
----