type of if statement used for operator overloading?

Jonathan M Davis jmdavisProg at gmx.com
Tue Feb 5 22:37:04 PST 2013


On Wednesday, February 06, 2013 07:24:10 Jeremy DeHaan wrote:
> I've seen operator overloading done 3 different ways. In the
> examples I provide they all compile and work as far as I can
> tell. Is there any major difference between using a static if vs
> a regular if, or any situation that one would be better than the
> other?
> 
> 
> struct Something1
> {
>     Something1 opUnary(string s)()
>     {
>         if (s == "-")
>         {
>            return stuff;
>         }
>     }
> 
> }

Don't do this. You want to be generating different functions for different 
overloaded operators. This just introduces extra runtime overhead. It also 
fails to deal with all of the possible values of s.

> struct Something2
> {
>     Something2 opUnary(string s)()
>     {
>         static if (s == "-")
>         {
>            return stuff;
>         }
>     }
> 
> }

This is better but again fails to deal with all of the possible values of s. 
You'll get a nasty error message if a different value gets passed in.

> Also, I realize that if I wanted to overload just a single
> operator and that was all, I could do:
> 
> struct Something3
> {
>     Something3 opUnary(string s)()
>        if (s == "-")
>     {
> 
>         return stuff;
> 
>     }
> 
> }
> 
> But I am more curious about the first two.

The last one is by far the best, because it protects against values for s that 
you don't intend to overload for. You can with the second example if you 
really want to and have multiple operators that you want to overload with the 
same function, but you still need a template constraint to protect against 
values that you don't intend to handle. Pretty much _every_ template that you 
write should have a template constraint on it.

And in many cases, overloaded operators should just use string mixins. For 
instance, core.time.Duration does this:

Duration opBinary(string op, D)(D rhs) @safe const pure nothrow
    if((op == "+" || op == "-") &&
       (is(_Unqual!D == Duration) ||
        is(_Unqual!D == TickDuration)))
{
    static if(is(_Unqual!D == Duration))
        return Duration(mixin("_hnsecs " ~ op ~ " rhs._hnsecs"));
    else if(is(_Unqual!D == TickDuration))
        return Duration(mixin("_hnsecs " ~ op ~ " rhs.hnsecs"));
}

It uses static ifs to differentiate between Duration and TickDuration (since 
they require different code), but the code doesn't differentiate between the 
operators. Rather, it just mixes in the string, and it'll do the right thing 
in both cases. The template constraint already protects against operators that 
it doesn't actually overload.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list