Why can't I get value_type from iterator_traits?
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?
c++ types iterator typename iterator-traits
add a comment |
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?
c++ types iterator typename iterator-traits
I generally usestd::decay
for this. Though, I'm reluctant to post this as an answer because I'm not entirely comfortable with why it seems to fix all of these problems. So it might not be the right solution. You would writeconst typename std::iterator_traits<std::decay_t<decltype(foo)>>::value_type bar = 1;
.
– François Andrieux
Jan 9 at 15:29
@FrançoisAndrieux Yeah, I was hoping I could make this work for either avector
or an array...decay
would still work there though... so maybe that's best?
– Jonathan Mee
Jan 9 at 15:32
@JonathanMee It does work for non-pointer iterator types as well. In my experience it fixes this kind of problem every time and magically works. Though again, the fact that it seems like magic to me leaves me nervous about recommending it.
– François Andrieux
Jan 9 at 15:33
@FantasticMrFox That change is intended to deal withvolatile T*
. It does not add a specialization forT* const
.
– xskxzr
Jan 10 at 2:53
add a comment |
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?
c++ types iterator typename iterator-traits
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?
c++ types iterator typename iterator-traits
c++ types iterator typename iterator-traits
edited Jan 10 at 1:53
Peter Mortensen
13.6k1984111
13.6k1984111
asked Jan 9 at 15:23
Jonathan MeeJonathan Mee
21.6k1064167
21.6k1064167
I generally usestd::decay
for this. Though, I'm reluctant to post this as an answer because I'm not entirely comfortable with why it seems to fix all of these problems. So it might not be the right solution. You would writeconst typename std::iterator_traits<std::decay_t<decltype(foo)>>::value_type bar = 1;
.
– François Andrieux
Jan 9 at 15:29
@FrançoisAndrieux Yeah, I was hoping I could make this work for either avector
or an array...decay
would still work there though... so maybe that's best?
– Jonathan Mee
Jan 9 at 15:32
@JonathanMee It does work for non-pointer iterator types as well. In my experience it fixes this kind of problem every time and magically works. Though again, the fact that it seems like magic to me leaves me nervous about recommending it.
– François Andrieux
Jan 9 at 15:33
@FantasticMrFox That change is intended to deal withvolatile T*
. It does not add a specialization forT* const
.
– xskxzr
Jan 10 at 2:53
add a comment |
I generally usestd::decay
for this. Though, I'm reluctant to post this as an answer because I'm not entirely comfortable with why it seems to fix all of these problems. So it might not be the right solution. You would writeconst typename std::iterator_traits<std::decay_t<decltype(foo)>>::value_type bar = 1;
.
– François Andrieux
Jan 9 at 15:29
@FrançoisAndrieux Yeah, I was hoping I could make this work for either avector
or an array...decay
would still work there though... so maybe that's best?
– Jonathan Mee
Jan 9 at 15:32
@JonathanMee It does work for non-pointer iterator types as well. In my experience it fixes this kind of problem every time and magically works. Though again, the fact that it seems like magic to me leaves me nervous about recommending it.
– François Andrieux
Jan 9 at 15:33
@FantasticMrFox That change is intended to deal withvolatile T*
. It does not add a specialization forT* const
.
– xskxzr
Jan 10 at 2:53
I generally use
std::decay
for this. Though, I'm reluctant to post this as an answer because I'm not entirely comfortable with why it seems to fix all of these problems. So it might not be the right solution. You would write const typename std::iterator_traits<std::decay_t<decltype(foo)>>::value_type bar = 1;
.– François Andrieux
Jan 9 at 15:29
I generally use
std::decay
for this. Though, I'm reluctant to post this as an answer because I'm not entirely comfortable with why it seems to fix all of these problems. So it might not be the right solution. You would write const typename std::iterator_traits<std::decay_t<decltype(foo)>>::value_type bar = 1;
.– François Andrieux
Jan 9 at 15:29
@FrançoisAndrieux Yeah, I was hoping I could make this work for either a
vector
or an array... decay
would still work there though... so maybe that's best?– Jonathan Mee
Jan 9 at 15:32
@FrançoisAndrieux Yeah, I was hoping I could make this work for either a
vector
or an array... decay
would still work there though... so maybe that's best?– Jonathan Mee
Jan 9 at 15:32
@JonathanMee It does work for non-pointer iterator types as well. In my experience it fixes this kind of problem every time and magically works. Though again, the fact that it seems like magic to me leaves me nervous about recommending it.
– François Andrieux
Jan 9 at 15:33
@JonathanMee It does work for non-pointer iterator types as well. In my experience it fixes this kind of problem every time and magically works. Though again, the fact that it seems like magic to me leaves me nervous about recommending it.
– François Andrieux
Jan 9 at 15:33
@FantasticMrFox That change is intended to deal with
volatile T*
. It does not add a specialization for T* const
.– xskxzr
Jan 10 at 2:53
@FantasticMrFox That change is intended to deal with
volatile T*
. It does not add a specialization for T* const
.– xskxzr
Jan 10 at 2:53
add a comment |
3 Answers
3
active
oldest
votes
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).
It's worth pointing out @FantasticMrFox's comment that theremove_cv_t
happens automatically in C++20. So I'd say this is indeed the preferred solution.
– Jonathan Mee
Jan 9 at 18:59
add a comment |
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
.
1
It “fixes” the problem by weakening the type contract offoo
. This is hardly a good solution:foo
should be declaredconst
. Don’t remove that!
– Konrad Rudolph
Jan 9 at 15:37
1
I agree with @KonradRudolph that it would be best to leavefoo
asconst
. I feel like it would be better to instead fix the template argument given toiterator_traits
.
– François Andrieux
Jan 9 at 15:40
1
@KonradRudolph I've updated the answer but it really depends on what the OP wants to do with it. You can normally reassignconst_iterators
from containers so removing theconst
makes it behave the same.
– NathanOliver
Jan 9 at 15:47
add a comment |
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.
I meannext
still works on it fine? It's the same argument againstconst char* const
but in some cases this compiles into more optimized code than aconst char*
– Jonathan Mee
Jan 9 at 18:25
@JonathanMeestd::next
requires an argument that satisfy LegacyInputIterator, which requires the type to be CopyAssignable through the LegacyIterator requirement. An Iterator type is intrinsically not const qualifiable.
– Julien Villemure-Fréchette
Jan 9 at 21:04
@JulienVillrmure-Fréchette I assume from your statement: "An Iterator type is intrinsically not const qualifiable." That you mean that the only way to modify a constant iterator would be to operate on a copy of it? And that generally the point of an iterator is modification?
– Jonathan Mee
Jan 9 at 21:47
Trivial example to a meaningful iterator constant: the end of a range. Though I also don't see a use-case for const cbegin...
– stefan
Jan 10 at 5:35
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54113330%2fwhy-cant-i-get-value-type-from-iterator-traits%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
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).
It's worth pointing out @FantasticMrFox's comment that theremove_cv_t
happens automatically in C++20. So I'd say this is indeed the preferred solution.
– Jonathan Mee
Jan 9 at 18:59
add a comment |
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).
It's worth pointing out @FantasticMrFox's comment that theremove_cv_t
happens automatically in C++20. So I'd say this is indeed the preferred solution.
– Jonathan Mee
Jan 9 at 18:59
add a comment |
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).
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).
edited Jan 9 at 15:41
answered Jan 9 at 15:32
Jarod42Jarod42
116k12102182
116k12102182
It's worth pointing out @FantasticMrFox's comment that theremove_cv_t
happens automatically in C++20. So I'd say this is indeed the preferred solution.
– Jonathan Mee
Jan 9 at 18:59
add a comment |
It's worth pointing out @FantasticMrFox's comment that theremove_cv_t
happens automatically in C++20. So I'd say this is indeed the preferred solution.
– Jonathan Mee
Jan 9 at 18:59
It's worth pointing out @FantasticMrFox's comment that the
remove_cv_t
happens automatically in C++20. So I'd say this is indeed the preferred solution.– Jonathan Mee
Jan 9 at 18:59
It's worth pointing out @FantasticMrFox's comment that the
remove_cv_t
happens automatically in C++20. So I'd say this is indeed the preferred solution.– Jonathan Mee
Jan 9 at 18:59
add a comment |
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
.
1
It “fixes” the problem by weakening the type contract offoo
. This is hardly a good solution:foo
should be declaredconst
. Don’t remove that!
– Konrad Rudolph
Jan 9 at 15:37
1
I agree with @KonradRudolph that it would be best to leavefoo
asconst
. I feel like it would be better to instead fix the template argument given toiterator_traits
.
– François Andrieux
Jan 9 at 15:40
1
@KonradRudolph I've updated the answer but it really depends on what the OP wants to do with it. You can normally reassignconst_iterators
from containers so removing theconst
makes it behave the same.
– NathanOliver
Jan 9 at 15:47
add a comment |
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
.
1
It “fixes” the problem by weakening the type contract offoo
. This is hardly a good solution:foo
should be declaredconst
. Don’t remove that!
– Konrad Rudolph
Jan 9 at 15:37
1
I agree with @KonradRudolph that it would be best to leavefoo
asconst
. I feel like it would be better to instead fix the template argument given toiterator_traits
.
– François Andrieux
Jan 9 at 15:40
1
@KonradRudolph I've updated the answer but it really depends on what the OP wants to do with it. You can normally reassignconst_iterators
from containers so removing theconst
makes it behave the same.
– NathanOliver
Jan 9 at 15:47
add a comment |
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
.
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
.
edited Jan 9 at 15:42
answered Jan 9 at 15:31
NathanOliverNathanOliver
91.2k15129193
91.2k15129193
1
It “fixes” the problem by weakening the type contract offoo
. This is hardly a good solution:foo
should be declaredconst
. Don’t remove that!
– Konrad Rudolph
Jan 9 at 15:37
1
I agree with @KonradRudolph that it would be best to leavefoo
asconst
. I feel like it would be better to instead fix the template argument given toiterator_traits
.
– François Andrieux
Jan 9 at 15:40
1
@KonradRudolph I've updated the answer but it really depends on what the OP wants to do with it. You can normally reassignconst_iterators
from containers so removing theconst
makes it behave the same.
– NathanOliver
Jan 9 at 15:47
add a comment |
1
It “fixes” the problem by weakening the type contract offoo
. This is hardly a good solution:foo
should be declaredconst
. Don’t remove that!
– Konrad Rudolph
Jan 9 at 15:37
1
I agree with @KonradRudolph that it would be best to leavefoo
asconst
. I feel like it would be better to instead fix the template argument given toiterator_traits
.
– François Andrieux
Jan 9 at 15:40
1
@KonradRudolph I've updated the answer but it really depends on what the OP wants to do with it. You can normally reassignconst_iterators
from containers so removing theconst
makes it behave the same.
– NathanOliver
Jan 9 at 15:47
1
1
It “fixes” the problem by weakening the type contract of
foo
. This is hardly a good solution: foo
should be declared const
. Don’t remove that!– Konrad Rudolph
Jan 9 at 15:37
It “fixes” the problem by weakening the type contract of
foo
. This is hardly a good solution: foo
should be declared const
. Don’t remove that!– Konrad Rudolph
Jan 9 at 15:37
1
1
I agree with @KonradRudolph that it would be best to leave
foo
as const
. I feel like it would be better to instead fix the template argument given to iterator_traits
.– François Andrieux
Jan 9 at 15:40
I agree with @KonradRudolph that it would be best to leave
foo
as const
. I feel like it would be better to instead fix the template argument given to iterator_traits
.– François Andrieux
Jan 9 at 15:40
1
1
@KonradRudolph I've updated the answer but it really depends on what the OP wants to do with it. You can normally reassign
const_iterators
from containers so removing the const
makes it behave the same.– NathanOliver
Jan 9 at 15:47
@KonradRudolph I've updated the answer but it really depends on what the OP wants to do with it. You can normally reassign
const_iterators
from containers so removing the const
makes it behave the same.– NathanOliver
Jan 9 at 15:47
add a comment |
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.
I meannext
still works on it fine? It's the same argument againstconst char* const
but in some cases this compiles into more optimized code than aconst char*
– Jonathan Mee
Jan 9 at 18:25
@JonathanMeestd::next
requires an argument that satisfy LegacyInputIterator, which requires the type to be CopyAssignable through the LegacyIterator requirement. An Iterator type is intrinsically not const qualifiable.
– Julien Villemure-Fréchette
Jan 9 at 21:04
@JulienVillrmure-Fréchette I assume from your statement: "An Iterator type is intrinsically not const qualifiable." That you mean that the only way to modify a constant iterator would be to operate on a copy of it? And that generally the point of an iterator is modification?
– Jonathan Mee
Jan 9 at 21:47
Trivial example to a meaningful iterator constant: the end of a range. Though I also don't see a use-case for const cbegin...
– stefan
Jan 10 at 5:35
add a comment |
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.
I meannext
still works on it fine? It's the same argument againstconst char* const
but in some cases this compiles into more optimized code than aconst char*
– Jonathan Mee
Jan 9 at 18:25
@JonathanMeestd::next
requires an argument that satisfy LegacyInputIterator, which requires the type to be CopyAssignable through the LegacyIterator requirement. An Iterator type is intrinsically not const qualifiable.
– Julien Villemure-Fréchette
Jan 9 at 21:04
@JulienVillrmure-Fréchette I assume from your statement: "An Iterator type is intrinsically not const qualifiable." That you mean that the only way to modify a constant iterator would be to operate on a copy of it? And that generally the point of an iterator is modification?
– Jonathan Mee
Jan 9 at 21:47
Trivial example to a meaningful iterator constant: the end of a range. Though I also don't see a use-case for const cbegin...
– stefan
Jan 10 at 5:35
add a comment |
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.
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.
answered Jan 9 at 16:57
Julien Villemure-FréchetteJulien Villemure-Fréchette
46517
46517
I meannext
still works on it fine? It's the same argument againstconst char* const
but in some cases this compiles into more optimized code than aconst char*
– Jonathan Mee
Jan 9 at 18:25
@JonathanMeestd::next
requires an argument that satisfy LegacyInputIterator, which requires the type to be CopyAssignable through the LegacyIterator requirement. An Iterator type is intrinsically not const qualifiable.
– Julien Villemure-Fréchette
Jan 9 at 21:04
@JulienVillrmure-Fréchette I assume from your statement: "An Iterator type is intrinsically not const qualifiable." That you mean that the only way to modify a constant iterator would be to operate on a copy of it? And that generally the point of an iterator is modification?
– Jonathan Mee
Jan 9 at 21:47
Trivial example to a meaningful iterator constant: the end of a range. Though I also don't see a use-case for const cbegin...
– stefan
Jan 10 at 5:35
add a comment |
I meannext
still works on it fine? It's the same argument againstconst char* const
but in some cases this compiles into more optimized code than aconst char*
– Jonathan Mee
Jan 9 at 18:25
@JonathanMeestd::next
requires an argument that satisfy LegacyInputIterator, which requires the type to be CopyAssignable through the LegacyIterator requirement. An Iterator type is intrinsically not const qualifiable.
– Julien Villemure-Fréchette
Jan 9 at 21:04
@JulienVillrmure-Fréchette I assume from your statement: "An Iterator type is intrinsically not const qualifiable." That you mean that the only way to modify a constant iterator would be to operate on a copy of it? And that generally the point of an iterator is modification?
– Jonathan Mee
Jan 9 at 21:47
Trivial example to a meaningful iterator constant: the end of a range. Though I also don't see a use-case for const cbegin...
– stefan
Jan 10 at 5:35
I mean
next
still works on it fine? It's the same argument against const char* const
but in some cases this compiles into more optimized code than a const char*
– Jonathan Mee
Jan 9 at 18:25
I mean
next
still works on it fine? It's the same argument against const char* const
but in some cases this compiles into more optimized code than a const char*
– Jonathan Mee
Jan 9 at 18:25
@JonathanMee
std::next
requires an argument that satisfy LegacyInputIterator, which requires the type to be CopyAssignable through the LegacyIterator requirement. An Iterator type is intrinsically not const qualifiable.– Julien Villemure-Fréchette
Jan 9 at 21:04
@JonathanMee
std::next
requires an argument that satisfy LegacyInputIterator, which requires the type to be CopyAssignable through the LegacyIterator requirement. An Iterator type is intrinsically not const qualifiable.– Julien Villemure-Fréchette
Jan 9 at 21:04
@JulienVillrmure-Fréchette I assume from your statement: "An Iterator type is intrinsically not const qualifiable." That you mean that the only way to modify a constant iterator would be to operate on a copy of it? And that generally the point of an iterator is modification?
– Jonathan Mee
Jan 9 at 21:47
@JulienVillrmure-Fréchette I assume from your statement: "An Iterator type is intrinsically not const qualifiable." That you mean that the only way to modify a constant iterator would be to operate on a copy of it? And that generally the point of an iterator is modification?
– Jonathan Mee
Jan 9 at 21:47
Trivial example to a meaningful iterator constant: the end of a range. Though I also don't see a use-case for const cbegin...
– stefan
Jan 10 at 5:35
Trivial example to a meaningful iterator constant: the end of a range. Though I also don't see a use-case for const cbegin...
– stefan
Jan 10 at 5:35
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54113330%2fwhy-cant-i-get-value-type-from-iterator-traits%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I generally use
std::decay
for this. Though, I'm reluctant to post this as an answer because I'm not entirely comfortable with why it seems to fix all of these problems. So it might not be the right solution. You would writeconst typename std::iterator_traits<std::decay_t<decltype(foo)>>::value_type bar = 1;
.– François Andrieux
Jan 9 at 15:29
@FrançoisAndrieux Yeah, I was hoping I could make this work for either a
vector
or an array...decay
would still work there though... so maybe that's best?– Jonathan Mee
Jan 9 at 15:32
@JonathanMee It does work for non-pointer iterator types as well. In my experience it fixes this kind of problem every time and magically works. Though again, the fact that it seems like magic to me leaves me nervous about recommending it.
– François Andrieux
Jan 9 at 15:33
@FantasticMrFox That change is intended to deal with
volatile T*
. It does not add a specialization forT* const
.– xskxzr
Jan 10 at 2:53