2
votes

I've made and exercise on variable number of parameters:

import std.stdio;

void main() {
    
    enum Operation { add, subtract, multiply, divide }
    
    struct Calculation {
        Operation op;
        double first;
        double second;
    }
    
    double calculate1(in Calculation c) {
        double result;
        switch (c.op) {
            case Operation.add : {
                result = c.first+c.second;
                break;
            }
            default : {
                break;
            }
        }
        return result;
    }
    
    double[] calculate(in Calculation[] ccs...){
        double[] result;
        foreach(c;ccs){ 
            result ~= calculate1(c);
        }
        return result;
    }
    
    writeln(calculate1(Calculation(Operation.add, 1.1, 2.2)));
    
    writeln(calculate
            ([Calculation(Operation.add, 2.1, 2.2)
             ,Calculation(Operation.add, 2.1, 2.2)
             ,Calculation(Operation.add, 2.1, 2.2)
             ,Calculation(Operation.add, 2.1, 2.2)]
             )
           );
}

It works ok:

3.3

[4.3, 4.3, 4.3, 4.3]

Then I've tried to try overload function calculate and change calculate1 name to calculate. And it brings this errors:

(27): Error: declaration calculate is already defined

(38): Error: function calculate (const(Calculation) c) is not callable using argument types (Calculation[])

I can't get it. Is this kind of declaration brings ambiguity and compiler tries to send Calculation[] as Calculation argument? And is it possible to overload calculate function in this program?

EDIT: When removing ... from line double[] calculate(in Calculation[] ccs...){ ambiguity vanishes. Now having types Calculation[] and Calculation as arguments, error message is still the same.

EDIT2. Interesting find by rcorre. Moving overloaded function calculate from main to upper scope this overload totally works.

1

1 Answers

1
votes

(27): Error: declaration calculate is already defined

Your calculate function is defined inside of main, but nested functions cannot be overloaded.

The compiler is refusing to create a second definition of calculate within main.

(38): Error: function calculate (const(Calculation) c) is not callable using argument types (Calculation[])

At this point, it only has 1 definition of calculate, which cannot be called with a Calculation[].

Try defining calculate outside of main or renaming one of the functions.

If you're really set on overloading, you could use a typesafe variadic function:

auto calculate(Args...)(in Args ccs){
    static if (Args.length == 1) {
        // single arg, return a double
        auto c = ccs[0];
        double result;
        switch (c.op) {
            case Operation.add : 
                result = c.first+c.second;
                break;

            default : 
                break;

        }
        return result;
    }
    else {
        // multi arg, return a double[]
        double[] result;
        foreach(c;ccs){ 
            result ~= calculate(c);
        }
        return result;
    }
}

The above can't be passed a Calculation[], but instead would need to be called as calculate(calculation1, calculation2, ...), though you could certainly extend it to handle getting an array. We need a template here because you are overloading the return type (one call may return a double, another returns a double[]).