I find it difficult to choose between size_t and ptrdiff_t for the index type, which should be able to store a negative value.
To be precise, in my code I need to implement an array. I get its length (in the constructor) as type size_t , and when I overload the [] operator , I need the index to be of type ptrdiff_t (not size_t ), since I want to allow negative indexes, as this example shows:
std::size_t length = 50; MyVector<int> vec(length); vec[0] = 10; MyVector<int> vec2 = vec+1; std::cout << vec2[-1] << std::endl;
The problem that arises from this construction is that the range of available indexes is limited by the maximum ptrdiff_t value, and on some machines this upper limit is less than the maximum size_t value .
i.e. std::numeric_limits<std::ptrdiff_t>::max() < std::numeric_limits<std::size_t>::max()
So the problem is that the user can create an array with a size larger than the maximum ptrdiff_t value (but still in the size_t range, of course) , but he wonβt have access to the elements of the array that prevail over the maximum value ptrdiff_t because their indexes overflow to a negative number. On my machine, this reduces the available indexes in half! (since both size_t and ptrdiff_t are 64 bits, but one is unsigned and the other is signed )
Here are the solutions I came up with, but, unfortunately, none of them are perfect:
In the constructor, let's say a length of type ptrdiff_t instead of size_t and add a check that checks that the given length is not negative.
Pros: Solves the problem, since now I could access all the elements in the array and still allow negative indexes.
Cons: It limits the maximum possible length of the array. (for example, as I said earlier, on my machine it is cut in half)
Leave things as they are, but in the [] operator enter an index to enter size_t , and use the fact that a negative value will overflow.
i.e. to this index add the difference between the element we are currently pointing at, and
for example, in my example before, since vec2 points to the second element in arary, the [] operator will look something like
template<class T> T& MyVector<T>::operator[] (std::ptrdiff_t index) {
Pros: Now we can access all the elements in the array.
Cons: Use becomes clumsy and ugly. For example, if we create a vector of size std::numeric_limits<std::size_t>::max() , then to access the last element we need to access the element '-1':
MyVector<int> big_vector(std::numeric_limits<std::size_t>::max()); big_vector[-1] = 5;
source share