Błąd w rozumowaniu metody remove_if

0

Witam, mam problem z tą linijką

vec2.erase(remove_if(vec2.begin(),vec2.end(),Pred2(27,83)),vec2.end())

dokładnie chodzi mi o to, że

remove_if(vec2.begin(),vec2.end(),Pred2(27,83)

remove_if zwraca mi iterator na koniec mojej "nowej tablicy", natomiast metoda erase( ) działa na dwa sposoby dla konkretnego iterator erase( iterator _Where ) i dla iterator erase( iterator _First, iterator _Last ) Czyli jakby nie patrzeć pierwszy argument jaki przyjmuje metoda erase dla vec2 jest to iterator na koniec nowego rozmiaru, a ja potrzebuję iterator na początek. Czyli według mnie brakuje mi iteratora wskazujacego na poczatek. Niestety, wiem że moje rozumowanie jest błędne jeżeli ktoś by mógł mi to trochę przybliżyć bym był bardzo wdzięczny .

 
#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <set>
#include <cstdlib>
#include <list>
#include <time.h>
using namespace std;
class Gen {
private:
    int a, b;

public:
    Gen(int x, int y)
        : a(x)
        , b(y)
    {
    }
    int operator()()
    {
        return rand() % (b - a + 1) + a;
    }
};
struct Pred2 {
    int a, b;
    Pred2(int x, int y)
        : a(x)
        , b(y)
    {
    }
    bool operator()(int x)
    {
        if (x > a && x < b) {
            return true;
        }
        return false;
    }
};
int main()
{
    Gen gen2(1, 200);
    vector<int> vec2(200);
    generate(vec2.begin(), vec2.end(), gen2);
    vec2.erase(remove_if(vec2.begin(), vec2.end(), Pred2(27, 83)), vec2.end());
    copy(vec2.begin(), vec2.end(), ostream_iterator<int>(cout, " "));

    return 0;
}

1

http://en.cppreference.com/w/cpp/algorithm/remove

Removes all elements satisfying specific criteria from the range [first, last) and returns a past-the-end iterator for the new end of the range.

To załóżmy, że masz wektor

vector <int>a = { 1, 2, 3, 4, 5, 6, 7} i robisz remove_if(a.begin(), a.end(), isOdd)

efekt będzie taki

{ 2, 4, 6, 1 /* A */, 3, 5, 7 } /* ... B == a.end(), poza wektorem */
Przy czym począwszy od A nie jest powiedziane co dokładnie będzie w tym wektorze (patrz posty poniżej), gwarantowana jest jedynie ważność iteratorów.

A to to co zwrócił remove_if, czyli to co byłoby endem po faktycznym skasowaniu reszty (zarazem początek obszaru do skasowania), natomiast B==a.end() i jest nadal ważny, bo:

Relative order of the elements that remain is preserved and the physical size of the container is unchanged. Iterators pointing to an element between the new logical end and the physical end of the range are still dereferenceable, but the elements themselves have unspecified values (as per MoveAssignable post-condition).

Jak zawołasz erase(A, B) to zostanie Ci {2, 4, 6}

Jaśniej? ;)

0
alagner napisał(a):

efekt będzie taki

{ 2, 4, 6, 1 /* A */, 3, 5, 7 } /* ... B == a.end(), poza wektorem */

Nieprawda. Efekt będzie taki:
{ 2, 4, 6, /*A*/ 4, 5, 6, 7 } /* ... B == a.end(), poza wektorem */

4

@MarekR22 bzdury
Iterators pointing to an element between the new logical end and the physical end of the range are still dereferenceable, but the elements themselves have unspecified values (as per MoveAssignable post-condition).
http://en.cppreference.com/w/cpp/algorithm/remove

@alagner unspecified value bierze się stąd, że te elementy są przenoszone. Natomiast konstruktor przenoszący zostawia obiekt ** z którego przenosimy ** właśnie w stanie unspecified value.

17.6.5.15:
Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.

1 użytkowników online, w tym zalogowanych: 0, gości: 1