A file named rational.d containing
Rational!(I1) rational(I1, I2)(I1 , I2)
{
return typeof(return)();
}
struct Rational(Int)
{
bool opEquals(Rhs)(Rhs _) {}
}
@nogc unittest
{
auto _ = rational(1, 2);
}
compiled as
dmd -main -unittest -preview=in rational.d
fails to link as
rational.o:__main.d:_D36TypeInfo_S8rational__T8RationalTiZQm6__initZ: error: undefined reference to '_D6object10_xopEqualsFMxPvMxQeZb'
Compiling without -preview=in as
dmd -main -unittest rational.d
makes the linking pass.
Comment #1 by per.nordlow — 2020-06-21T22:51:12Z
Same linker error is triggered when replacing `opEquals` with `opCmp` as with
Rational!(I1) rational(I1, I2)(I1 , I2)
{
return typeof(return)();
}
struct Rational(Int)
{
bool opCmp(Rhs)(Rhs _) {}
}
@nogc unittest
{
auto _ = rational(1, 2);
}
instead fails to link as
rational.o:__main.d:_D36TypeInfo_S8rational__T8RationalTiZQm6__initZ: error: undefined reference to '_D6object7_xopCmpFMxPvMxQeZb'
Comment #2 by boris2.9 — 2020-06-22T09:43:07Z
Just quoting forum's reply https://forum.dlang.org/thread/[email protected]
You can get more info compiling with "-verrors=spec"
"(spec:1) Error: template rational.Rational!int.Rational.opEquals cannot deduce function from argument types !()(const(Rational!int)) const, candidates are:"
From reading the docs for function opEquals (https://dlang.org/spec/operatoroverloading.html#equals).
It shows a templated version with a const modifier.
If you change the function signature to:
bool opEquals(Rhs)(Rhs _) const {return true;} // Note the 'const', and putting some return back because dustmite removed it
The program links fine.
So it seems a compiler error is gagged that should be exposed and also could be improved.
Comment #3 by default_357-line — 2020-06-22T09:54:14Z
May relate to https://issues.dlang.org/show_bug.cgi?id=19091 - sometimes the compiler doesn't notice misinstantiation of structs. Then the failed struct is cached for the template parameter and treated as successful.
Comment #4 by robert.schadek — 2024-12-13T19:09:35Z