Problem with using std.math: abs and std.complex: abs at the same time

Simen Kjærås simen.kjaras at gmail.com
Wed Sep 18 12:37:28 UTC 2019


On Wednesday, 18 September 2019 at 12:03:28 UTC, berni wrote:
> The following code doesn't compile:
>
>>import std.stdio;
>>
>>void main()
>>{
>>    import std.complex: abs, complex;
>>    import std.math: abs;
>>
>>    auto a = complex(1.0,1.0);
>>    auto b = 1.0;
>>
>>    writeln(abs(a));
>>    writeln(abs(b));
>>}
>
> The error message depends on the order of the two import 
> statements. Seems like the second import is actually ignored.

     import std.complex: abs, complex;

Is treated by the compiler as if you'd written something somewhat 
like this:

     static import std.complex;
     alias abs = std.complex.abs;
     alias complex = std.complex.complex;

When you add

     import std.math: abs;

It's treated like:

     static import std.math;
     alias abs = std.math.abs;

In other words, we have two aliases with the same name inside a 
function scope, and the compiler can't do that (try doing it 
explicitly, as in the 'treated like' sections above - you'll get 
a compilation error). This is related to why you can't have 
overloaded nested functions:

     unittest {
         void fun() {}
         void fun(int i) {} // declaration fun is already defined
     }

How to resolve this, though? The simplest solution is to not use 
selective imports:

     import std.math;
     import std.complex;

     writeln(abs(complex(1.0,1.0)));
     writeln(abs(1.0));

If you absolutely can't contaminate the scope with all the unused 
symbols in std.math and std.complex, you *can* do this:

import std.stdio;

unittest {
     import std.complex : complex;
     static import std.math;

     alias abs = MergeOverloads!(std.complex.abs, std.math.abs);

     auto a = complex(1.0,1.0);
     auto b = 1.0;

     writeln(abs(a));
     writeln(abs(b));
}

template MergeOverloads(T...) {
     alias MergeOverloads = T[0];
     static if (T.length > 1) {
         alias MergeOverloads = MergeOverloads!(T[1..$]);
     }
}

I would however label that a horrible hack.

FWIW, I've filed this issue: 
https://issues.dlang.org/show_bug.cgi?id=20226

--
   Simen


More information about the Digitalmars-d-learn mailing list