Home > Software engineering >  c : Is it valid to subtract an iterator from an element pointer to get a valid index?
c : Is it valid to subtract an iterator from an element pointer to get a valid index?

Time:11-24

I came across the following code:

for (int i = 0; i < subspan.size(); i  ) {
  ...
  int size = size_table[&(subspan[i]) - fullspan.begin()];
  ...
}

subspanand fullspan are both of type std::span (actually absl::Span from Google's Abseil library, but they seem to be pretty much the same as std::span) and are views into the same data array (with fullspan spanning the entire array).

Is this valid and well defined code? It seems to depend on the iterator being converted to the corresponding pointer value when the - operator is applied together with a lhs pointer.

CodePudding user response:

Is it valid to subtract an iterator from an element pointer to get a valid index?

It could be, depending on how the iterator is defined. For example, it works if the iterator is a pointer of the same type, and points to an element of the same array.

However, no generic iterator concept specifies such operation, and so such operation isn't guaranteed to work with any standard iterator. Hence, it's not a portable assumption that it would work in generic code.

Is this valid and well defined code?

The iterator type in question is defined to be the pointer type, so that condition is satisfied. Abseil is neither thoroughly documented nor specified, so it's hard to say whether that's an intentional feature, or incidental implementation detail. If it's latter, then the code may break in future versions of Abseil.

CodePudding user response:

Reading the implementation of absl::Span, we have:

template <typename T>
class Span {
...
 public:
  using element_type = T;
  using pointer = T*;
  using const_pointer = const T*;
  using reference = T&;
...
  using iterator = pointer;
...
  constexpr iterator begin() const noexcept { return data(); }
  constexpr reference operator[](size_type i) const noexcept { return *(data()   i); }
...
}

So your expression boils down to plain pointer arithmetic. Note that there is no check on whether both spans refer to the same base span, but you asserted that was not the case.

  • Related