Reputation: 333
I am implementing an Array class with constexpr methods. In my design, I allow an iterator to exceed the end() because instead of doing: while ( it != arr.end() ), I do: while ( arr.finished(it) ) by comparing the two raw pointers internally. It works with non constexpr array instances, but not with constexpr ones because of the following problem:
#include <array>
int main()
{
static constexpr std::array<int, 3> arr{};
constexpr const int* ptr = &arr[0];
constexpr const int* ptr2 = (const int*)ptr + 4;// error
return 0;
}
I got the message:
array subscript value 4 is outside the bounds of array type _Type {aka const int [3]}|
With Windows 10 and gcc10.1.0 located at C:\cygwin64\usr\local\bin
I don't even dereference the pointer so I kinda feel angry by the "careness" of the compiler.
My question is:
What can I do to make this code compile and keep my design choice of having out of bound iterators ? (not just past last end which is already allowed by the compiler). Can I disable the out of bound error with gcc ?
Upvotes: 0
Views: 271
Reputation: 238311
You cannot perform pointer arithmetic beyond the bounds of an array in C++. The behaviour of such operation is undefined. And a program that has undefined behaviour in a constantly evaluated expression is ill-formed and therefore a compiler is allowed to refuse compiling it (and is required to diagnose it).
You cannot make this work with pointers, but you could possibly implement a custom iterator class to be used with your custom Array class instead.
Upvotes: 1
Reputation: 122133
I don't even dereference the pointer so I kinda feel angry by the "careness" of the compiler.
What you observe is not an overly carefull compiler. Incrementing a pointer more than one past the last element of an array is not allowed. You need not dereference the pointer to be in trouble.
You are only allowed to increment the pointer up to one past the last element (and you may not dereference that one-past-the-last pointer).
In a non-const expression context incrementing ptr + 4
would be undefined behavior. During compile time however, there is no undefined behavior and the compiler diagnoses the problem.
Upvotes: 1