c++iteratorconst-correctnessconst-iteratoriterator-traits

Why is std::iterator_traits::value_type non-const even for a const_iterator?


In the C++ standard library, why is

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

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?


Solution

  • 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.