## digitalmars.D - Overloading opEquals(T)(T y)

• Charles McAnany (19/19) Feb 07 2011 Hi, all. So I'm trying to make a BigRational struct, to get more comfort...
• bearophile (15/29) Feb 07 2011 One possible solution:
• spir (10/39) Feb 08 2011 I just thought at this alternative between a constraint and a static if ...
• Steven Schveighoffer (32/77) Feb 08 2011 The point of constraints are to intercept the compilation earlier. For ...
• spir (16/55) Feb 08 2011 Thank you very much, Steven.
• Steven Schveighoffer (9/29) Feb 08 2011 No, there are multiple functions generated, and in each function, the
Charles McAnany <mcanance rose-hulman.edu> writes:
```Hi, all. So I'm trying to make a BigRational struct, to get more comfortable
with D. I'm working on the opEquals part now, and I'm having some difficulty.
I'd like to write an equality checker for two BigRationals, and have all other
comparisons make a BigRational of the rhs and then forward that to the first
equality checker.

bool opEquals(Tdummy = void)(BigRational y){
auto temp = this-y;
if (temp.numerator == 0)
return true;
return false;
}

bool opEquals(T)(T y){
return this == BigRational(y);
}

But this is an ambiguity error. Certainly, I could write opEquals(T: int)(T
y), opEquals(T:long)(T y), and so on and so on, but I feel there must be a
more elegant solution. Any ideas?
Thanks,
Charles
```
Feb 07 2011
bearophile <bearophileHUGS lycos.com> writes:
```Charles McAnany:

Hi, all. So I'm trying to make a BigRational struct, to get more comfortable
with D.

I suggest to ask similar questions in the D.learn newsgroup.

bool opEquals(Tdummy = void)(BigRational y){
auto temp = this-y;
if (temp.numerator == 0)
return true;
return false;
}

bool opEquals(T)(T y){
return this == BigRational(y);
}

But this is an ambiguity error.

One possible solution:

bool opEquals(T)(T y) if (is(T == BigRational)) { ... }
bool opEquals(T)(T y) if (!is(T == BigRational)) { ... }

Another solution:

bool opEquals(T)(T y) {
static if (is(T == BigRational)) {
// ...
} else {
// ...
}
}

Bye,
bearophile
```
Feb 07 2011
spir <denis.spir gmail.com> writes:
```On 02/08/2011 12:16 AM, bearophile wrote:
Charles McAnany:

Hi, all. So I'm trying to make a BigRational struct, to get more comfortable
with D.

I suggest to ask similar questions in the D.learn newsgroup.

bool opEquals(Tdummy = void)(BigRational y){
auto temp = this-y;
if (temp.numerator == 0)
return true;
return false;
}

bool opEquals(T)(T y){
return this == BigRational(y);
}

But this is an ambiguity error.

One possible solution:

bool opEquals(T)(T y) if (is(T == BigRational)) { ... }
bool opEquals(T)(T y) if (!is(T == BigRational)) { ... }

Another solution:

bool opEquals(T)(T y) {
static if (is(T == BigRational)) {
// ...
} else {
// ...
}
}

Bye,
bearophile

I just thought at this alternative between a constraint and a static if a few
hours ago. In which case, and according to which reasoning, would one choose
one or the other? (I chose static if only for the very bad reason I can hardly
stand is().)

Denis
--
_________________
vita es estrany
spir.wikidot.com
```
Feb 08 2011
"Steven Schveighoffer" <schveiguy yahoo.com> writes:
```On Tue, 08 Feb 2011 10:52:35 -0500, spir <denis.spir gmail.com> wrote:

On 02/08/2011 12:16 AM, bearophile wrote:
Charles McAnany:

Hi, all. So I'm trying to make a BigRational struct, to get more
comfortable
with D.

I suggest to ask similar questions in the D.learn newsgroup.

bool opEquals(Tdummy = void)(BigRational y){
auto temp = this-y;
if (temp.numerator == 0)
return true;
return false;
}

bool opEquals(T)(T y){
return this == BigRational(y);
}

But this is an ambiguity error.

One possible solution:

bool opEquals(T)(T y) if (is(T == BigRational)) { ... }
bool opEquals(T)(T y) if (!is(T == BigRational)) { ... }

Another solution:

bool opEquals(T)(T y) {
static if (is(T == BigRational)) {
// ...
} else {
// ...
}
}

Bye,
bearophile

I just thought at this alternative between a constraint and a static if
a few hours ago. In which case, and according to which reasoning, would
one choose one or the other? (I chose static if only for the very bad
reason I can hardly stand is().)

The point of constraints are to intercept the compilation earlier.  For
the discussed example, it's not as important.  Let's try a smaller example.

What is the difference between:

bool opEquals(T)(T y) if (is(T == BigRational)) {...}

and

bool opEquals(T)(T y)
{
static if(is(T == BigRational)) {...}
else static assert(0, "invalid type");
}

With an example like myBigRational == 5?

The difference is, with the first, the compiler simply skips compiling
that function due to the constraint.  With the second, the compiler still
tries to compile the opEquals.  The difference is really in the error the
compiler generates.  With the first, the error is "no function found", the
second is "function doesn't compile".  This is all pretty much equivalent,
until you want to overload the template.  Perhaps you want to overload it
in different modules.  With the second method, this is impossible, all
overloads must be in the single definition.  This also makes it somewhat
less readable.

Plus, with the second, its really easy to forget that "else static
assert", meaning the function will compile, and simply do nothing
(actually, it won't compile because it doesn't return a value, but still,
that error message is going to be way more confusing than "no function
found").

I'd say a rule of thumb is, if the entire function is going to be
different based on the types, you should use a constraint.  If there is
one small difference in the function, then using the static if might be a
better approach, but you still might want to use the constraints to
restrict to what you expect.

-Steve
```
Feb 08 2011
spir <denis.spir gmail.com> writes:
```On 02/08/2011 05:17 PM, Steven Schveighoffer wrote:
On Tue, 08 Feb 2011 10:52:35 -0500, spir <denis.spir gmail.com> wrote:

On 02/08/2011 12:16 AM, bearophile wrote:
Charles McAnany:

Hi, all. So I'm trying to make a BigRational struct, to get more comfortable
with D.

I just thought at this alternative between a constraint and a static if a few
hours ago. In which case, and according to which reasoning, would one choose
one or the other? (I chose static if only for the very bad reason I can
hardly stand is().)

The point of constraints are to intercept the compilation earlier. For the
discussed example, it's not as important. Let's try a smaller example.

What is the difference between:

bool opEquals(T)(T y) if (is(T == BigRational)) {...}

and

bool opEquals(T)(T y)
{
static if(is(T == BigRational)) {...}
else static assert(0, "invalid type");
}

Thank you very much, Steven.
I'd say: in the first case, there are as many functions as constraints variants
(provided other variants are implemented, indeed) triggered by actual calls to
opEquals.
Tell me if i'm right on this: In the second case, there is a single function
generated, and branches of static if are inserted according to actual calls. Is
that right? If yes then I don't really care of this use of static f (I'm aware
there are other, maybe more relevant, use cases).

With an example like myBigRational == 5?

The difference is, with the first, the compiler simply skips compiling that
function due to the constraint. With the second, the compiler still tries to
compile the opEquals. The difference is really in the error the compiler
generates. With the first, the error is "no function found", the second is
"function doesn't compile". This is all pretty much equivalent, until you want
to overload the template. Perhaps you want to overload it in different modules.
With the second method, this is impossible, all overloads must be in the single
definition. This also makes it somewhat less readable.

Plus, with the second, its really easy to forget that "else static assert",
meaning the function will compile, and simply do nothing (actually, it won't
compile because it doesn't return a value, but still, that error message is
going to be way more confusing than "no function found").

Right.

I'd say a rule of thumb is, if the entire function is going to be different
based on the types, you should use a constraint. If there is one small
difference in the function, then using the static if might be a better
approach, but you still might want to use the constraints to restrict to what
you expect.

Right again, makes full sense now.

Denis
--
_________________
vita es estrany
spir.wikidot.com
```
Feb 08 2011
"Steven Schveighoffer" <schveiguy yahoo.com> writes:
```On Tue, 08 Feb 2011 11:49:47 -0500, spir <denis.spir gmail.com> wrote:

On 02/08/2011 05:17 PM, Steven Schveighoffer wrote:

What is the difference between:

bool opEquals(T)(T y) if (is(T == BigRational)) {...}

and

bool opEquals(T)(T y)
{
static if(is(T == BigRational)) {...}
else static assert(0, "invalid type");
}

Thank you very much, Steven.
I'd say: in the first case, there are as many functions as constraints
variants (provided other variants are implemented, indeed) triggered by
actual calls to opEquals.
Tell me if i'm right on this: In the second case, there is a single
function generated, and branches of static if are inserted according to
actual calls. Is that right? If yes then I don't really care of this use
of static f (I'm aware there are other, maybe more relevant, use cases).

No, there are multiple functions generated, and in each function, the
correct static if branch is compiled.  It's technically no different
code-generation wise than the constraint version.

The difference comes in the compiler decision of whether to compile a
function or not, and who is responsible for reporting the error (in the
first, the compiler reports the error, in the second, you are responsible
for reporting the error via static assert).

-Steve
```
Feb 08 2011