Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

const_iterator and constness of const_iterator::value_type

Why in STL

std::iterator_traits<const T*>::value_type

is the same type as

std::iterator_traits<T*>::value_type

Why it is designed like that? Shouldn't the first be const T and the second only T? How are you supposed to take the underlying const correct type of an iterator? I know you can write your own template class and specialization and get it from

    std::iterator_traits<const T*>::pointer

but shouldn't there be a member typedef that holds it?

like image 470
Sogartar Avatar asked Oct 10 '12 12:10

Sogartar


2 Answers

Constness doesn't matter for the value type, since a value implies a copy. The std::iterator_traits<const T*>::reference is a const T& however.

For example, you can write this function:

template <class Iterator>
typename std::iterator_traits<Iterator>::value_type getValue(Iterator i)
{
  return *i;
}

and it works perfectly fine whether Iterator is a const T * or a T *.

like image 162
Vaughn Cato Avatar answered Sep 21 '22 00:09

Vaughn Cato


It allows me to do this:

std::iterator_traits<I>::value_type val = *iter;
val += 5;
doSomething(val);

But that's harder if value_type is const, because I need to use remove_const.

If I don't want to get a modifiable value then it doesn't matter whether value_type is const or not:

const std::iterator_traits<I>::value_type cval = *iter;
std::iterator_traits<I>::reference        ref  = *iter;

Both of these work for const iterators and non-const iterators, and both work whether value_type is const or not, but the first example only works for const iterators if their value_type is non-const.

How are you supposed to take the underlying const correct type of an iterator?

An iterator doesn't necessarily have an underlying type of its own, an iterator usually refers to some range or some collection, and that collection is what has an underlying type. e.g std::list<int>::const_iterator's value_type is std::list<int>::value_type, which is int not const int.

You don't necessarily want to know what the underlying type is anyway, it's more likely you want to know what the result of *iter is, and that's what iterator_traits<I>::reference tells you.

like image 22
Jonathan Wakely Avatar answered Sep 23 '22 00:09

Jonathan Wakely