Thread overview
Quick help on version function parameter
Feb 18, 2015
Jonathan Marler
Feb 18, 2015
Adam D. Ruppe
Feb 19, 2015
Jonathan Marler
Feb 19, 2015
Marc Schütz
February 18, 2015
Does anyone know a good way to support versioned function parameters?  Say, in one version I want a variable to be a global and in another I want it to be a parameter.

version(GlobalVersion)
{
    int x;
    void foo()
    {
        // A huge function that uses x
    }
} else {
    void foo(int x)
    {
        // A huge function that uses x (same code as GlobalVersion)
    }
}

The problem with this is that the code is duplicated.  Is there a way to do this versioning without having 2 copies of the same function body?  The following definitely does not work:

version(GlobalVersion)
{
    int x;
    void foo()
} else {
    void foo(int x)
}
    {
        // A huge function that uses x
    }
February 18, 2015
I'd write a foo_impl which always takes a parameter. Then do the versioned foo() functions which just forward to it:

void foo_impl(int x) { long function using x here }

version(globals) {
   int x;
   void foo() {
      foo_impl(x);
   }
} else {
   void foo(int x) { foo_impl(x); }
}

Minimal duplication with both interfaces.
February 19, 2015
On Wednesday, 18 February 2015 at 23:49:26 UTC, Adam D. Ruppe wrote:
> I'd write a foo_impl which always takes a parameter. Then do the versioned foo() functions which just forward to it:
>
> void foo_impl(int x) { long function using x here }
>
> version(globals) {
>    int x;
>    void foo() {
>       foo_impl(x);
>    }
> } else {
>    void foo(int x) { foo_impl(x); }
> }
>
> Minimal duplication with both interfaces.

That kinda defeats the purpose of why I want this.  It's for performance reasons.  I need one version to have NO arguments and one version to have one ref argument.
February 19, 2015
On Thursday, 19 February 2015 at 01:39:19 UTC, Jonathan Marler wrote:
> On Wednesday, 18 February 2015 at 23:49:26 UTC, Adam D. Ruppe wrote:
>> I'd write a foo_impl which always takes a parameter. Then do the versioned foo() functions which just forward to it:
>>
>> void foo_impl(int x) { long function using x here }
>>
>> version(globals) {
>>   int x;
>>   void foo() {
>>      foo_impl(x);
>>   }
>> } else {
>>   void foo(int x) { foo_impl(x); }
>> }
>>
>> Minimal duplication with both interfaces.
>
> That kinda defeats the purpose of why I want this.  It's for performance reasons.  I need one version to have NO arguments and one version to have one ref argument.

If it's a `ref` argument (your original example doesn't have one), are you sure there will be a performance problem?

Anyway, how about using a template and an alias, respectively:

    void foo_impl(ref ExpensiveStruct x) { ... }

    version(globals) {
        ExpensiveStruct x;
        void foo()() {
            foo_impl(x);
        }
    } else {
        alias foo = foo_impl;
    }

That way, you'd force `foo` to be instantiated at the call site, making it more likely to be inlinable. In the non-global case, there will be no overhead at all because of the `alias`.

But, as always for things related to performance: profile first, then optimize.