I've tested the following code with GCC 4.8, that doesn't compile because we can't form reference to void.
#include <iterator>
int main()
{
std::iterator_traits<void*> test;
}
Does that mean that void* isn't an iterator ? (meaning the concept here)
EDIT:
Okay the question was ill formed. What I'm actually asking is why does C++ need such a behavior for void* ? Is it for safety concerns, i.e preventing people from writing bad thing ?
Because while deferencing a void is illegal, pointer arithmetic is :
int main()
{
std::uint8_t test[] = {1,2,3};
void * wut = test;
std::uint8_t * p2 = static_cast<std::uint8_t *>(wut + 1);
std::cout << std::hex << static_cast<int>(*p2) << std::endl;
}
So even if, as you said, void hasn't a size, from the point of view of GCC, it does. And it is the size of the smallest adressable unit in a computer.
An iterator is an object (like a pointer) that points to an element inside the container. We can use iterators to move through the contents of the container. They can be visualised as something similar to a pointer pointing to some location and we can access content at that particular location using them.
The most obvious form of an iterator is a pointer. A pointer can point to elements in an array and can iterate through them using the increment operator (++).
However, since a default-constructed container iterator is not associated with any particular container, there is no good value it could take. Therefore it is just an uninitialized variable and the only legal operation to do with it is to assign a valid iterator to it.
Any iterator type needs to be dereferenceable and incrementable, but you can not dereference or increment void*
. Since you linked cppreference.com
, it starts here.
Regarding your updated question: It is for safety reasons. If you want a pointer to the individual bytes in memory, you'd use char*
, unsigned char*
or something like that. void*
is basically just a way to store an address and it is not supposed to be used to access anything. Only when you know what it points to, you are supposed to cast it to a pointer to that type.
The reason you are allowed to add (or subtract) from it is AFAIK for backward compatibility. For a void* p;
you are allowed to write p += 1;
, but you are not allowed to increment it with ++p;
as per
5.3.2 Increment and decrement [expr.pre.incr]
1 The operand of prefix
++
is modified by adding1
, or set totrue
if it isbool
(this use is deprecated). The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type or a pointer to a completely-defined object type.
(emphasis mine).
Per §3.9.1/9
and §5.7
, Type void
is not a complete type and additive operators can not be applied to incomplete pointer types:
The void type has an empty set of values. The void type is an incomplete type that cannot be > completed...
... operand is (shall be) a pointer to a completely-defined object ...
Therefore you can not have an iterator for voids.
error: forming reference to void
Declaring std::iterator_traits
, it somewhere tries to declare a reference to the entry type which is void
in your case. but per §8.3.2/5
declaring a reference to void
is not legal, because you can not define a valid object of void
:
A reference shall be initialized to refer to a valid object
The answer is simple because you can not dereference void*
. Also void has no size so you cant move to the next item. The iterator type must be incremental and dereferenceable.
EDIT:-
Is it for safety concerns, i.e preventing people from writing bad thing ?
Yes this is for safety reason. You cant do what you have tried to do that in your edit. void*
is just used to store the address and if you are using it to access anything then it would not be allowed.
You can write wut = wut + 1
for void * wut
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With