Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why void* isn't an iterator type?

Tags:

c++

iterator

gcc

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.

like image 297
Nemikolh Avatar asked Oct 20 '13 20:10

Nemikolh


People also ask

What is Type iterator?

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.

Is a form of an iterator?

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 (++).

What is default value of iterator in C++?

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.


3 Answers

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 adding 1, or set to true if it is bool (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).

like image 152
Daniel Frey Avatar answered Nov 16 '22 01:11

Daniel Frey


Why you can't have an iterator for void type?

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.

 

Why you see that error?

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

like image 23
masoud Avatar answered Nov 16 '22 01:11

masoud


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

like image 21
Rahul Tripathi Avatar answered Nov 16 '22 00:11

Rahul Tripathi