[libcxx-commits] [PATCH] D107396: [libcxx][ranges] Add `ranges::iota_view`.

Arthur O'Dwyer via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Fri Aug 13 16:47:03 PDT 2021


Quuxplusone added inline comments.


================
Comment at: libcxx/include/__ranges/iota_view.h:257-260
+          if (__y.__value_ > __x.__value_) {
+            return difference_type(-difference_type(__y.__value_ - __x.__value_));
+          }
+          return difference_type(__x.__value_ - __y.__value_);
----------------
zoecarver wrote:
> cjdb wrote:
> > zoecarver wrote:
> > > cjdb wrote:
> > > > 
> > > The conditional expression here does not seem easier to read. I could see an argument for it to be the same difficulty, but to me it is harder to read than the if statement. I don't see a reason to change this. 
> > We're at a bit of an impasse then, because I find the if-statement approach to be the less-readable one.
> See discord discussion. 
IIUC, you're discussing the cascade that currently looks like this:
```
        if constexpr (__integer_like<_Start>) {
          if constexpr (__signed_integer_like<_Start>) {
            return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_));
          }
          if (__y.__value_ > __x.__value_) {
            return difference_type(-difference_type(__y.__value_ - __x.__value_));
          }
          return difference_type(__x.__value_ - __y.__value_);
        }
        return __x.__value_ - __y.__value_;
```
for which the Standard reference implementation is
```
if constexpr (is-integer-like<W>) {
  if constexpr (is-signed-integer-like<W>)
    return D(D(x.value_) - D(y.value_));
  else
    return (y.value_ > x.value_)
      ? D(-D(y.value_ - x.value_))
      : D(x.value_ - y.value_);
} else {
  return x.value_ - y.value_;
}
```
Personally I'd recommend sticking to the reference implementation (including the `?:`), to make it easy to verify that libc++ matches the Standard-mandated behavior (even though it is not obvious //what that behavior actually is!//). Alternatively, if we wanted to make it easy to //read// the code, one way to do that is to disentangle the nested ifs and turn it into a plain if-else-if ladder:
```
        if constexpr (!__integer_like<_Start>) {
          return __x.__value_ - __y.__value_;
        } else if constexpr (__signed_integer_like<_Start>) {
          return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_));
        } else if (__y.__value_ > __x.__value_) {
          return difference_type(-difference_type(__y.__value_ - __x.__value_));
        } else {
          return difference_type(__x.__value_ - __y.__value_);
        }
```
Writing it out longhand this way really illustrates the insanity of the reference implementation: each branch puts its explicit casts to `difference_type` in different places! Particularly the first and fourth branches (in the if-else-if ladder version above) are gratuitously different: the first uses an implicit conversion, the last an explicit conversion. If these conversions can have observably different behavior, something is seriously broken.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D107396/new/

https://reviews.llvm.org/D107396



More information about the libcxx-commits mailing list