Overloading opEquals(T)(T y)

Steven Schveighoffer schveiguy at yahoo.com
Tue Feb 8 08:17:48 PST 2011


On Tue, 08 Feb 2011 10:52:35 -0500, spir <denis.spir at 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


More information about the Digitalmars-d mailing list