I have the following for
statement in my code:
for (auto Iter = Target.begin(),
IterEnd = std::stable_partition(Target.begin(), Target.end(), Check);
Iter != IterEnd; ++Iter)
{ /* loop statement */ }
The point is that the loop doesn't modify elements of the container, so it would make sense to declare iterators as const_iterator
. I can easily solve the problem for the first using cbegin()
, but the second is more complex. I can't declare cbegin()
and cend()
inside stable_partition
, since of course stable_partition
needs non const_iterators
to do its work.
A possible solution is to replace auto with the proper type, which in this case was std::vector< std::string >::const_iterator
. This forces the conversion from iterator
to const_iterator
on the second assignment.
Though, I don't like it. Types can easily and rapidly become unmanageable, so I'm looking for a solution that lets me use auto, without the need to declare something weird outside the loop. Any suggestion?
The most clear solution in my opinion is to pull std::stable_partition
before the for
. This will result in an equivalent algorithm.
The problem is that stable_partition
returns a iterator that can modify elements. Fortunately there is an implicit conversion from container::iterator
to container::const_iterator
(for most standard containers). To make the conversion you can specify the type of IterEnd
with std::vector<T::const_iterator
, or decltyp(Target.cbegin()
or my personal preference:
auto Iter = Target.cbegin();
decltype(Iter) IterEnd = std::stable_partition(Target.begin(), Target.end(), Check);
for (; Iter != IterEnd; ++Iter)
{
}
For completeness you could keep all inside the for
if you wish but it's less readable in my opinion:
for (auto Iter = Target.cbegin(),
IterEnd = (decltype(Iter)) std::stable_partition(Target.begin(), Target.end(), Check);
Iter != IterEnd;
++Iter)
{}