opCmp with and without const

Jonathan M Davis newsgroup.d at jmdavisprog.com
Fri Dec 6 13:39:08 UTC 2019


On Friday, December 6, 2019 12:03:45 AM MST berni44 via Digitalmars-d-learn 
wrote:
> In std.typecons, in Tuple there are two opCmp functions, that are
> almost identical; they only differ by one being const and the
> other not:
>
>          int opCmp(R)(R rhs)
>          if (areCompatibleTuples!(typeof(this), R, "<"))
>          {
>              static foreach (i; 0 .. Types.length)
>              {
>                  if (field[i] != rhs.field[i])
>                  {
>                      return field[i] < rhs.field[i] ? -1 : 1;
>                  }
>              }
>              return 0;
>          }
>
>          int opCmp(R)(R rhs) const
>          if (areCompatibleTuples!(typeof(this), R, "<"))
>          {
>              static foreach (i; 0 .. Types.length)
>              {
>                  if (field[i] != rhs.field[i])
>                  {
>                      return field[i] < rhs.field[i] ? -1 : 1;
>                  }
>              }
>              return 0;
>          }
>
>
> What is the reason for having this? (I guess, that it's because
> the function may indirectly call opCmp of other types which may
> or may not be const.)
>
> My real question is: Can this code duplication be avoided
> somehow? (I ask, because I've got a PR running, which increases
> the size of these functions and it doesn't feel good to have two
> long, almost identical functions.)

The issue is that there's no guarantee that the types being wrapped have a
const opCmp. So, you can't just slap const or inout on Tuple's opCmp and
have it work, but you do want it to be const if it can be const. So, two
overloads are declared, and the template constraint takes care of checking
whether that particular overload can be instantiated.

A mixin could be used for the function bodies to avoid duplicating the
internals, and it may be possible to use template this parameters as Paul
Backus suggested (I'm not very familiar with template this parameters, so I
don't know how well they'll work in this particular case), but ultimately,
one way or another, you need to have a non-const opCmp declared for when the
wrapped types don't have an opCmp that works with const and a const or inout
opCmp for when the wrapped types do have an opCmp that works with const.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list