mercredi 23 août 2017

Clamp iterator value to end()

I have a vector with n Strings in it. Now lets say I want to "page" or "group" those strings in a map.

typedef std::vector<std::string> TStringVec;
TStringVec myVec;

//.. fill myVecwith n elements

typedef std::map<int, TStringVec>> TPagedMap;
TPagedMap myMap;

int ItemsPerPage = 3 // or whatever
int PagesRequired = std::ceil(myVec.size() / nItemsPerPage);
for (int Page = 0; Page < NumPagesMax; ++Page)
{
    TStringVec::const_iterator Begin = myVec.begin() + (ItemsPerPage * Page);
    TStringVec::const_iterator End = myVec.begin() + ItemsPerPage * (Page+1);
    myMap[Page] = TStringVec(Begin, End);
}

One can easily spot the problem here. When determining the end iterator, I risk leaving the allocated space by the vector.

Quick example: 5 elements in the vector, ItemsPerPage is 3. That means we need a total of 2 pages in the map to group all elements.

Now when hitting the last iteration, begin is pointing at myVec[3] but end is "pointing" to myVec[6]. Remember, myVec only has 5 elements.

Could this case be safely handled by swapping

TStringVec::const_iterator End = myVec.begin() + ItemsPerPage * (Page+1);

with

TStringVec::const_iterator End = std::min(myVec.begin() + ItemsPerPage * (Page+1), myVec.end() - 1); 

It compiles of course, and it seems to work. But I'm not sure if this can be considered a safe thing to do. Any advice or a definitive answer?

Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire