Thread overview
How to check for combinations of versions
May 05
Blatnik
May 05
Blatnik
May 05
Dennis
May 05

Is there any way to check for multiple conditions in a version statement?

For example, my platform may have Version_A and Version_B, and both versions provide some shiny feature I want to use. Is there some nice way to write:

version (Version_A || Version_B) {
  // Use the cool feature.
} else {
  // Do something less cool but portable.
}

Currently I resort to something like this, but I'm curious if there's a nicer way to do it.

version (Version_A) {
  enum Cool_Feature_Supported = true;
} else version (Version_B) {
  enum Cool_Feature_Supported = true;
} else {
  enum Cool_Feature_Supported = false;
}

...

void do_something_cool() {
  static if (Cool_Feature_Supported) {
    ...
  } else {
    ...
  }
}
May 05

On Wednesday, 5 May 2021 at 15:03:16 UTC, Blatnik wrote:

>

Currently I resort to something like this, but I'm curious if there's a nicer way to do it.

version (Version_A) {
  enum Cool_Feature_Supported = true;
} else version (Version_B) {
  enum Cool_Feature_Supported = true;
} else {
  enum Cool_Feature_Supported = false;
}

This is the officially-recommended way to do it. D's version system is deliberately restricted, in order to avoid the "#ifdef hell" that often plagues C and C++ projects.

However, if you really want something more expressive, and are confident in your ability to use the extra power responsibly, it is possible to work around these limitations:

template hasVersion(string identifier) {
    mixin(
        "version(", identifier, ") enum hasVersion = true;",
        "else enum hasVersion = false;"
    );
}

// Usage
static if (hasVersion!"Version_A" || hasVersion!"Version_B") {
    enum Cool_Feature_Supported = true;
} else {
    enum Cool_Feature_Supported = false;
}
May 05

On Wednesday, 5 May 2021 at 15:03:16 UTC, Blatnik wrote:

>

Is there any way to check for multiple conditions in a version statement?

No, and that's by design to discourage complex version logic.
The recommended approach is:

version (Version_A) version = Cool_Feature_Supported;
version (Version_B) version = Cool_Feature_Supported;

void do_something_cool() {
  version(Cool_Feature_Supported) {
    ...
  } else {
    ...
  }
}

May 05

On Wednesday, 5 May 2021 at 15:25:31 UTC, Paul Backus wrote:

>

However, if you really want something more expressive, and are confident in your ability to use the extra power responsibly, it is possible to work around these limitations:

template hasVersion(string identifier) {
    mixin(
        "version(", identifier, ") enum hasVersion = true;",
        "else enum hasVersion = false;"
    );
}

Hmm, I'll keep this in mind in case things start getting start getting more out of hand. Thanks! :)

Mixin strings are still kind of like black magic to me, so I prefer not to use them unless I really think they would help a lot. In this case, I only do this 3 times in the entire codebase, so it's not worth it yet.

And Dennis, sadly that wouldn't work for me since version = XYZ only affects the current module and I'm using this check in multiple modules.

Thanks for the help!