Reputation: 38939
I'm doing this:
const int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
const auto foo = cbegin(arr);
const typename iterator_traits<decltype(foo)>::value_type bar = 1;
I would have expected bar
to have the type int
. But instead I'm getting an error:
error C2039:
value_type
: is not a member ofstd::iterator_traits<_Ty *const >
Is this a problem with the const
do I need to strip that or something?
Upvotes: 13
Views: 1592
Reputation: 828
Declaring a const qualified iterator const auto foo = cbegin(arr);
is questionable. What use do you have for an iterator on which you cannot apply operator++()
? Also, the Iterator requirement requires the type int const *const
to be Copy Assignable; as such, the variable foo
does not satisfy the Iterator requirement. So strictly speaking, foo
is not an Iterator.
Upvotes: 1
Reputation: 180935
The issue here is with the line
const auto foo = cbegin(arr);
cbegin(arr)
is going to return a int const *
(pointer to const int) so applying const
to that with const auto foo
means foo
is a int const * const
(const pointer to const int)
std::iterator_traits
is only specialized for a T*
or T const*
so giving it a T* const
fails since there is no valid specialization.
You can fix this by removing the constness in the declaration of bar
with
const typename std::iterator_traits<std::remove_cv_t<decltype(foo)>>::value_type
or you can change foo
to
auto foo = std::cbegin(arr);
if you are okay with it not being const
.
Upvotes: 19
Reputation: 217810
Indeed the const
is problematic, you do basically:
std::iterator_traits<const int* const>::value_type // incorrect due to the last const
You might fix it by changing it to
std::iterator_traits<const int*>::value_type // Correct
You might use std::decay
or std::remove_cv
for that:
const typename std::iterator_traits<std::remove_cv_t<decltype(foo)>>::value_type
(or drop const
from foo
if relevant).
Upvotes: 8