Thread overview
How to check for combinations of versions
May 05, 2021
Blatnik
May 05, 2021
Paul Backus
May 05, 2021
Blatnik
May 05, 2021
Dennis
May 05, 2021

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, 2021

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, 2021

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, 2021

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!