Search code examples
c++unsignedsubtraction

Signed result of subtracted unsigned integers?


I'm trying to create a class analagous to vector<string> and another class analagous to its iterators (purely as an exercise from C++ Primer (exercise 14.28 for those interested)). The iterator class works by having a vector<string>::size_type member (called curr) to represent an index of the vector. I did not wish to paste the entire works because it's quite long, but I've reached some level of confusion when trying to define my own subtraction operator for the iterators. Ultimately it should work like subtracting two iterators, and produce a negative value if necessary. I have the function defined like this:

??? operator-(const iterator& lhs, const iterator& rhs){
    return (lhs.curr - rhs.curr);
}

Alternatively, another version of my confusion;

#include <vector>
#include <string>
#include <iostream>

using namespace std;

int main(){

    vector<string>::size_type x = 5, y = 3;

    ??? z = (y-x); //what should ??? be if I want -2?

    cout << z;

}

(y-x) is -2 but of course wraps back around to 4294967294 since it is a 32-bit unsigned expression, before storing it in z. I can't figure out how to define my return type so that if rhs (y) is further along in the sequence than lhs (x), the correct negative value is returned (stored in z).

I thought vector<string>::difference_type might do that trick but I found out that size_type represents a 32-bit unsigned integer while difference_type represents a 32-bit signed integer, so there will be an error of wrapping around with signed integers which is undefined behaviour - even though on my computer it produces the correct result. I could static_cast everything to long long int and return a long long int but I feel that would be a bit too brute forced.


Solution

  • The correct type to use is indeed vector<string>::difference_type. You can easily implement iterator subtraction like this:

    difference_type operator- (const iterator &lhs, const iterator &rhs)
    {
      if (rhs.curr >= lhs.curr) return static_cast<difference_type>(rhs - lhs);
      else return - static_cast<difference_type>(lhs - rhs);
    }
    

    Real implementations of the standard library probably don't necessarily need to do that, since they are usually targeted at a particular compiler and can use internal knowledge of how the compiler handles implementation-defined behaviour such as the result of converting an unsigned value to a signed type when outside of the signed range.