Iterate backwards using iterators - c++

For simplification of my question i will use std::string::iterator and std::string::reverse_iterator but the question is about iterators in general.
Is there any particular reason to iterate backwards using the following loop:
std::string s = "something";
for (std::string::reverse_iterator it = s.rbegin(); it != s.rend(); ++it)
rather than this one:
std::string s = "something";
std::string::iterator it = in.end();
while(it!=in.begin())
{
it--;
//do something
}

Reverse iterators allow you to reuse generic code because you can treat them like normal iterators, calling ++ to go backwards. For example:
#include <iostream>
#include <string>
template <class Iterator>
void printAll(Iterator begin, Iterator end)
{
for (auto it = begin; it != end; ++it) // ++ can mean "go backwards"
// if Iterator is a reverse
// iterator
{
std::cout << *it << "\n";
}
}
int main()
{
std::string s = "123";
printAll(s.begin(), s.end()); // prints 1, 2, 3
printAll(s.rbegin(), s.rend()); // prints 3, 2, 1
}
Notice how you do not need to write a reverse version for printAll using --.
Now, consider all the functions in <algorithm>. The existence of reverse iterators means that you can easily use all of them in a reverse manner. For example, there is std::copy_n, but not std::reverse_copy_n, but with reverse iterators, it's not necessary, because you can write something like this:
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
int main()
{
std::string input = "abcdef";
std::string output;
std::string output_reversed;
// copy the first 3 elements:
std::copy_n(input.begin(), 3, std::back_inserter(output));
// copy the first 3 elements going backwards, starting at the last one:
std::copy_n(input.rbegin(), 3, std::back_inserter(output_reversed));
std::cout << output << "\n"; // prints abc
std::cout << output_reversed << "\n"; // prints fed
}
For non-generic code, such as in your question, it's more of a style issue, with few technically sound arguments to prefer one over the other.

Since begin() points to the first member, and end() points to the member next to the last, that is all about clean code (since in case of using not reverse iterators you would do iterator decrement first, then the code you want to execute, then you will compare iterator with begin(), but it is wrong, since begin() points to an existing first element.
std::vector::end() at cplusplus.com

Related

Let iter be an std::iterator. Is there any difference between std::next(iter,1) and ++iter?

Please consider the following code:
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> v{1,2,3};
// implementation 1:
for(auto iter = v.begin(); iter !=v.end(); ++iter)
std::cout << *iter;
std::cout << std::endl;
// implementation 2:
for(auto iter = v.begin(); iter !=v.end(); iter = std::next(iter, 1))
std::cout << *iter;
std::cout << std::endl;
}
As you can see here implementation 1 and implementation 2 produce the same output. Is this always the case?
In your code there is no difference. Both will advance the iterator one step.
Just to give one example where it might matter, let's say we want to print the second element of a range, we can't write something like ++b.begin() since we can't apply ++ to an rvalue.
Here a code example.
#include <array>
#include <iostream>
int main()
{
std::array<int, 2> a = {2, 4};
//std::cout << *(++a.begin()); // This will fail
std::cout << *std::next(a.begin());
}
If we uncomment the first output line gcc says
prog.cc: In function 'int main()':
prog.cc:8:29: error: lvalue required as increment operand
8 | std::cout << *(++a.begin());
| ~~~~~~~^~
Live example
Yes iter = std::next(iter, 1) is equivalent to ++iter.
The only difference between std::next(iter, 1) and ++iter i can think of is that std::next doesn't modify the iterator it returns the copy of resultant iterator.
Also std::next is very useful in generic context where iterator can be random access , forward etc. it will use most appropriate way to advance the iterator.

Does std::unique invalidate vector iterators?

For this code:
std::vector<int> v = {...};
std::sort(v.begin(), v.end());
// Does this work?
std::size_t unique_count = std::unique(v.begin(), v.end()) - v.cbegin();
In the last line, I think since std::unique just moves stuffs around inside the vector and does not insert anything into it, no iterators should be invalidated, and so the way I'm calculating unique_count should be correct. But I want to make sure that is the case. Is it?
std::unique is an algorithm. All stl algorithms operate on ranges, not containers.
Although the algorithm may swap element contents, the iterators to those elements remain unchanged.
This is a guarantee.
If it were not, then this could not work:
#include <algorithm>
#include <vector>
#include <iostream>
#include <array>
int main()
{
auto unique_size = [](auto&& container)
{
std::sort(std::begin(container), std::end(container));
return std::unique(std::begin(container), std::end(container)) - std::cbegin(container);
};
std::cout << unique_size(std::vector<int> {6,5,4,4,3,2,1}) << std::endl;
std::cout << unique_size(std::array<int,7> {6,5,4,4,3,2,1}) << std::endl;
int x[] = {6,5,4,4,3,2,1};
std::cout << unique_size(x) << std::endl;
// Does this work? yes.
}
mandated output:
6
6
6
std::unique return an iterator to one position past the last 'unique' element in the container.
auto last = std::unique(v.begin(), v.end());
Then the range [last, v.end()) contains whatever, you can't rely on v.cbegin(). Instead:
auto unique_count = std::distance(v.begin(), last);
will do the trick.
http://en.cppreference.com/w/cpp/algorithm/unique

how to find duplicates in std::vector<string> and return a list of them?

So if I have a vector of words like:
Vec1 = "words", "words", "are", "fun", "fun"
resulting list: "fun", "words"
I am trying to determine which words are duplicated, and return an alphabetized vector of 1 copy of them. My problem is that I don't even know where to start, the only thing close to it I found was std::unique_copy which doesn't exactly do what I need. And specifically, I am inputting a std::vector<std::string> but outputting a std::list<std::string>. And if needed, I can use functor.
Could someone at least push me in the right direction please? I already tried reading stl documentation,but I am just "brain" blocked right now.
In 3 lines (not counting the vector and list creation nor the superfluous line-breaks in name of readability):
vector<string> vec{"words", "words", "are", "fun", "fun"};
list<string> output;
sort(vec.begin(), vec.end());
set<string> uvec(vec.begin(), vec.end());
set_difference(vec.begin(), vec.end(),
uvec.begin(), uvec.end(),
back_inserter(output));
EDIT
Explanation of the solution:
Sorting the vector is needed in order to use set_difference() later.
The uvec set will automatically keep elements sorted, and eliminate duplicates.
The output list will be populated by the elements of vec - uvec.
Make an empty std::unordered_set<std::string>
Iterator your vector, checking whether each item is a member of the set
If it's already in the set, this is a duplicate, so add to your result list
Otherwise, add to the set.
Since you want each duplicate only listed once in the results, you can use a hashset (not list) for the results as well.
IMO, Ben Voigt started with a good basic idea, but I would caution against taking his wording too literally.
In particular, I dislike the idea of searching for the string in the set, then adding it to your set if it's not present, and adding it to the output if it was present. This basically means every time we encounter a new word, we search our set of existing words twice, once to check whether a word is present, and again to insert it because it wasn't. Most of that searching will be essentially identical -- unless some other thread mutates the structure in the interim (which could give a race condition).
Instead, I'd start by trying to add it to the set of words you've seen. That returns a pair<iterator, bool>, with the bool set to true if and only if the value was inserted -- i.e., was not previously present. That lets us consolidate the search for an existing string and the insertion of the new string together into a single insert:
while (input >> word)
if (!(existing.insert(word)).second)
output.insert(word);
This also cleans up the flow enough that it's pretty easy to turn the test into a functor that we can then use with std::remove_copy_if to produce our results quite directly:
#include <set>
#include <iterator>
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
class show_copies {
std::set<std::string> existing;
public:
bool operator()(std::string const &in) {
return existing.insert(in).second;
}
};
int main() {
std::vector<std::string> words{ "words", "words", "are", "fun", "fun" };
std::set<std::string> result;
std::remove_copy_if(words.begin(), words.end(),
std::inserter(result, result.end()), show_copies());
for (auto const &s : result)
std::cout << s << "\n";
}
Depending on whether I cared more about code simplicity or execution speed, I might use an std::vector instead of the set for result, and use std::sort followed by std::unique_copy to produce the final result. In such a case I'd probably also replace the std::set inside of show_copies with an std::unordered_set instead:
#include <unordered_set>
#include <iterator>
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
class show_copies {
std::unordered_set<std::string> existing;
public:
bool operator()(std::string const &in) {
return existing.insert(in).second;
}
};
int main() {
std::vector<std::string> words{ "words", "words", "are", "fun", "fun" };
std::vector<std::string> intermediate;
std::remove_copy_if(words.begin(), words.end(),
std::back_inserter(intermediate), show_copies());
std::sort(intermediate.begin(), intermediate.end());
std::unique_copy(intermediate.begin(), intermediate.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
}
This is marginally more complex (one whole line longer!) but likely to be substantially faster when/if the number of words gets very large. Also note that I'm using std::unique_copy primarily to produce visible output. If you just want the result in a collection, you can use the standard unique/erase idiom to get unique items in intermediate.
In place (no additional storage). No string copying (except to result list). One sort + one pass:
#include <string>
#include <vector>
#include <list>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
vector<string> vec{"words", "words", "are", "fun", "fun"};
list<string> dup;
sort(vec.begin(), vec.end());
const string empty{""};
const string* prev_p = ∅
for(const string& s: vec) {
if (*prev_p==s) dup.push_back(s);
prev_p = &s;
}
for(auto& w: dup) cout << w << ' ';
cout << '\n';
}
You can get a pretty clean implementation using a std::map to count the occurrences, and then relying on std::list::sort to sort the resulting list of words. For example:
std::list<std::string> duplicateWordList(const std::vector<std::string>& words) {
std::map<std::string, int> temp;
std::list<std::string> ret;
for (std::vector<std::string>::const_iterator iter = words.begin(); iter != words.end(); ++iter) {
temp[*iter] += 1;
// only add the word to our return list on the second copy
// (first copy doesn't count, third and later copies have already been handled)
if (temp[*iter] == 2) {
ret.push_back(*iter);
}
}
ret.sort();
return ret;
}
Using a std::map there seems a little wasteful, but it gets the job done.
Here's a better algorithm than the ones other people have proposed:
#include <algorithm>
#include <vector>
template<class It> It unique2(It const begin, It const end)
{
It i = begin;
if (i != end)
{
It j = i;
for (++j; j != end; ++j)
{
if (*i != *j)
{ using std::swap; swap(*++i, *j); }
}
++i;
}
return i;
}
int main()
{
std::vector<std::string> v;
v.push_back("words");
v.push_back("words");
v.push_back("are");
v.push_back("fun");
v.push_back("words");
v.push_back("fun");
v.push_back("fun");
std::sort(v.begin(), v.end());
v.erase(v.begin(), unique2(v.begin(), v.end()));
std::sort(v.begin(), v.end());
v.erase(unique2(v.begin(), v.end()), v.end());
}
It's better because it only requires swap with no auxiliary vector for storage, which means it will behave optimally for earlier versions of C++, and it doesn't require elements to be copyable.
If you're more clever, I think you can avoid sorting the vector twice as well.

How to check if the iterator is initialized?

If I use a default constructor for an iterator, how to check if it was assigned later on?
For pointers, I could do this :
int *p = NULL;
/// some code
if ( NULL == p ) {
// do stuff
}
How do I do the above for iterators?
Is it possible at all?
#include <iostream>
#include <list>
int main ()
{
std::list<int>::iterator it;
if ( NULL == it ) // this fails
{
std::cout<<"do stuff" << std::endl;
}
}
I managed to find this in the current standard (c++03 ). 24.1 p 5 tells :
Just as a regular pointer to an array guarantees that there is a
pointer value pointing past the last element of the array, so for any
iterator type there is an iterator value that points past the last
element of a corresponding container. These values are called
past-the-end values. Values of an iterator i for which the expression
*i is defined are called dereferenceable. The library never assumes
that past-the-end values are dereferenceable. Iterators can also have
singular values that are not associated with any container. [Example:
After the declaration of an uninitialized pointer x (as with int* x;),
x must always be assumed to have a singular value of a pointer. ]
Results of most expressions are undefined for singular values; the
only exception is an assignment of a non-singular value to an iterator
that holds a singular value. In this case the singular value is
overwritten the same way as any other value. Dereferenceable values
are always non- singular.
(Emphasis mine)
So the answer is : no, it is not possible.
Most iterators don't have any global special values in the same way that all pointers can be NULL. Typically, though, you'll be working with specific containers, and if you keep one iterator per container, then you can use end() as the sentinel value:
std::list<int> mylist;
std::list<int>::iterator it = mylist.end();
/* do stuff */
if (it == mylist.end()) { ... }
I'm not sure if insertion/deletion invalidates the end() iterator, though, so if you're planning on modifying your container, maybe save a copy of the original end, too:
std::list<int>::iterator end = mylist.end(), it = end;
if (it == end) { ... }
Though again I'm actually not sure if it's well-defined to compare two invalid iterators (in the event that the two do get invalidated).
This question has already been treated in Stackoverflow. The quintessence is that the default constructor initializes an iterator to a singular value, and the only addmissible operation on it is to assign it another iterator value. In particular it is not possible to query the value of such unitialized iterator. Therefore it is a good programming practice to initialize the iterator to a specific value of a specific container, which then can be tested for.
Since there is no default value for iterators (like there is NULL for pointers), in situation where i need a common default value for a Object::iterator (before any actual Object has been created) I create a dummy static variable and use its ::end() as the default.
Update : This only works for Release, because in DEBUG (or with _HAS_ITERATOR_DEBUGGING=1) comparison operators check if both iterators point to the same object/container.
For example for vector<int> I would do :
class A
{
public :
A() : myIterator1(dummyVector.end()), myIterator2(dummyVector.end()) {}
// needed iterators
vector<int>::iterator myIterator1;
vector<int>::iterator myIterator2;
static const vector<int> dummyVector;
}
#define IT_NULL A::dummyObject.end()
void maint() {
A::dummyObject = vector<int>(); // initialize the Null iterator
A a;
if(a.myIterator1 == IT_NULL) cout << "Iterator not yet initialized";
}
You can't. ll you can do is compare against list end
it != mylist.end();
In C++, uninitialized local variables can have any value i.e it contains simply garbage. That implies, you cannot check it against some well-defined value, to determine if the variable is uninitialized or not.
Not only that if the variable is not initialized and you write this:
if ( NULL == it ) // this fails
then it invokes undefined behavior.
Maybe you should always assign a predefined value, like NULL, after creating the iterator. Later you can easily check against NULL.
This will make your code more portable, as you will not depend on what starting values the uninitialized variables take at the beginning.
if(std::list<int>::iterator() == it)
But I suspect... may it's possible, that a valid iterator could pass the comparison.
Better to avoid these situations. If it's impossible store the iterator by a pointer.
std::auto_ptr<std::list<int>::iterator> it;
The best way to do this I can think of is something like
#include <utility>
#include <map>
#include <typeinfo>
#include <string>
namespace nulliterators {
typedef std::map<std::string, void*> nullcntT;
nullcntT nullcontainers;
template<class containerT>
typename containerT::iterator iterator() {
containerT* newcnt = new containerT();
std::string cnttypename = typeid(*newcnt).name();
nullcntT::iterator i = nullcontainers.find(cnttypename);
if (i==nullcontainers.end()) {
nullcontainers.insert(make_pair(cnttypename, newcnt));
return newcnt->end();
}else{
delete newcnt;
return (static_cast<containerT*>(i->second))->end();
}
}
}
template<class containerT>
typename containerT::iterator nulliterator() { return nulliterators::iterator<containerT>(); }
#include <list>
#include <iostream>
int main(){
std::list<int>::iterator nullinitized = nulliterator< std::list<int> >();
std::list<int> somelist;
std::list<int>::iterator initialized = somelist.end();
if (nullinitized == nulliterator< std::list<int> >())
std::cout << "nullinitized == nulliterator< std::list<int> >()\n"; //true
else
std::cout << "nullinitized != nulliterator< std::list<int> >()\n";
if (initialized == nulliterator< std::list<int> >())
std::cout << "initialized == nulliterator< std::list<int> >()\n";
else
std::cout << "initialized != nulliterator< std::list<int> >()\n"; //true
return 0;
}
but it's not exactly a safe solution (because it relies on the non-const global containers in nullcontainers).
As far as I know you must always initialize your iterators and the easiest way is to make them equal to 'container'.end()
In certain cases it looks like working, we had some problems with code that worked with VC6 and stopped working with VC2010. Look at this example compiled with g++ where it works for the vector but not for the map:
# Test iterator init, compile with: g++ test-iterator.cpp -o test-iterator
#include <iostream>
#include <vector>
#include <map>
int main()
{
std::vector<int> vec;
std::vector<int>::iterator it;
if (it != vec.end())
{
std::cout << "vector inside!" << std::endl;
}
else
{
std::cout << "vector outside!" << std::endl;
}
std::map<int, int> mp;
std::map<int, int>::iterator itMap;
if (itMap != mp.end())
{
std::cout << "map inside!" << std::endl;
}
else
{
std::cout << "map outside!" << std::endl;
}
return 0;
}
I used the following solution:
const MyList_t::const_iterator NullIterator(NULL);
const_iterator MyList_t::MyIterator;
Then a check is possible:
if (NullIterator != MyIterator) {}

Now to remove elements that match a predicate?

I have a source container of strings I want to remove any strings from the source container that match a predicate and add them into the destination container.
remove_copy_if and other algorithms can only reorder the elements in the container, and therefore have to be followed up by the erase member function. My book (Josuttis) says that remove_copy_if returns an iterator after the last position in the destination container. Therefore if I only have an iterator into the destination container, how can I call erase on the source container? I have tried using the size of the destination to determine how far back from the end of the source container to erase from, but had no luck. I have only come up with the following code, but it makes two calls (remove_if and remove_copy_if).
Can someone let me know the correct way to do this? I'm sure that two linear calls is not
the way to do this.
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
class CPred : public unary_function<string, bool>
{
public:
CPred(const string& arString)
:mString(arString)
{
}
bool operator()(const string& arString) const
{
return (arString.find(mString) == std::string::npos);
}
private:
string mString;
};
int main()
{
vector<string> Strings;
vector<string> Container;
Strings.push_back("123");
Strings.push_back("145");
Strings.push_back("ABC");
Strings.push_back("167");
Strings.push_back("DEF");
cout << "Original list" << endl;
copy(Strings.begin(), Strings.end(),ostream_iterator<string>(cout,"\n"));
CPred Pred("1");
remove_copy_if(Strings.begin(), Strings.end(),
back_inserter(Container),
Pred);
Strings.erase(remove_if(Strings.begin(), Strings.end(),
not1(Pred)), Strings.end());
cout << "Elements beginning with 1 removed" << endl;
copy(Strings.begin(), Strings.end(),ostream_iterator<string>(cout,"\n"));
cout << "Elements beginning with 1" << endl;
copy(Container.begin(), Container.end(),ostream_iterator<string>(cout,"\n"));
return 0;
}
With all due respect to Fred's hard work, let me add this: the move_if is no different than remove_copy_if at an abstract level. The only implementation level change is the end() iterator. You are still not getting any erase(). The accepted answer does not erase() the matched elements -- part of the OP's problem statement.
As for the OP's question: what you want is an in-place splice. This is possible for lists. However, with vectors this will not work. Read about when and how and why iterators are invalidated. You will have to take a two pass algorithm.
remove_copy_if and other algorithms can only reorder the elements in the container,
From SGI's documentation on remove_copy_if:
This operation is stable, meaning that the relative order of the elements that are copied is the same as in the range [first, last).
So no relative reordering takes place. Moreover, this is a copy, which means the elements from Source vector in your case, is being copied to the Container vector.
how can I call erase on the source container?
You need to use a different algorithm, called remove_if:
remove_if removes from the range [first, last) every element x such that pred(x) is true. That is, remove_if returns an iterator new_last such that the range [first, new_last) contains no elements for which pred is true. The iterators in the range [new_last, last) are all still dereferenceable, but the elements that they point to are unspecified. Remove_if is stable, meaning that the relative order of elements that are not removed is unchanged.
So, just change that remove_copy_if call to:
vector<string>::iterator new_last = remove_if(Strings.begin(),
Strings.end(),
Pred);
and you're all set. Just keep in mind, your Strings vector's range is no longer that defined by the iterators [first(), end()) but rather by [first(), new_last).
You can, if you want to, remove the remaining [new_last, end()) by the following:
Strings.erase(new_last, Strings.end());
Now, your vector has been shortened and your end() and new_last are the same (one past the last element), so you can use as always:
copy(Strings.begin(), Strings.end(), ostream_iterator(cout, "\"));
to get a print of the strings on your console (stdout).
I see your point, that you'd like to avoid doing two passes over your source container. Unfortunately, I don't believe there's a standard algorithm that will do this. It would be possible to create your own algorithm that would copy elements to a new container and remove from the source container (in the same sense as remove_if; you'd have to do an erase afterward) in one pass. Your container size and performance requirements would dictate whether the effort of creating such an algorithm would be better than making two passes.
Edit: I came up with a quick implementation:
template<typename F_ITER, typename O_ITER, typename FTOR>
F_ITER move_if(F_ITER begin, F_ITER end, O_ITER dest, FTOR match)
{
F_ITER result = begin;
for(; begin != end; ++begin)
{
if (match(*begin))
{
*dest++ = *begin;
}
else
{
*result++ = *begin;
}
}
return result;
}
Edit:
Maybe there is confusion in what is meant by a "pass". In the OP's solution, there is a call to remove_copy_if() and a call to remove_if(). Each of these will traverse the entirety of the original container. Then there is a call to erase(). This will traverse any elements that were removed from the original container.
If my algorithm is used to copy the removed elements to a new container (using begin() the original container for the output iterator will not work, as dirkgently demonstrated), it will perform one pass, copying the removed elements to the new container by means of a back_inserter or some such mechanism. An erase will still be required, just as with remove_if(). One pass over the original container is eliminated, which I believe is what the OP was after.
There will be copy_if and remove_if.
copy_if( Strings.begin(), Strings.end(),
back_inserter(Container), not1(Pred) );
Strings.erase( remove_if( Strings.begin(), Strings.end(), not1(Pred) ),
Strings.end() );
It is better to understand code where Predicate class answering "true" if something is present. In that case you won't need not1 two times.
Because std::find looks for substring not obligatory from the begin you need to change "beginning with 1" to "with 1" to avoid future misunderstanding of your code.
The whole reason why the remove_* algorithms do not erase elements is because it is impossible to "erase" an element by the iterator alone. You can't get container by iterator
This point is explained in more details in the book "Effective STL"
Use 'copy_if', followed by 'remove_if'. remove_copy_if does not modify the source.
On lists you can do better - reordering followed by splice.
If you don't mind having your strings in the same container, and having just an iterator to separate them, this code works.
#include "stdafx.h"
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;
class CPred : public unary_function<string, bool>
{
public:
CPred(const string& arString)
:mString(arString)
{
}
bool operator()(const string& arString) const
{
return (arString.find(mString) == std::string::npos);
}
private:
string mString;
};
int main()
{
vector<string> Strings;
Strings.push_back("213");
Strings.push_back("145");
Strings.push_back("ABC");
Strings.push_back("167");
Strings.push_back("DEF");
cout << "Original list" << endl;
copy(Strings.begin(), Strings.end(),ostream_iterator<string>(cout,"\n"));
CPred Pred("1");
vector<string>::iterator end1 =
partition(Strings.begin(), Strings.end(), Pred);
cout << "Elements matching with 1" << endl;
copy(end1, Strings.end(), ostream_iterator<string>(cout,"\n"));
cout << "Elements not matching with 1" << endl;
copy(Strings.begin(), end1, ostream_iterator<string>(cout,"\n"));
return 0;
}
remove*() don't relally remove elements, it simply reorders them and put them at the end of the collection and return a new_end iterator in the same container indicating where the new end is. You then need to call erase to remove the range from the vector.
source.erase(source.remove(source.begin(), source.end(), element), source.end());
remove_if() does the same but with a predicate.
source.erase(source.remove_if(source.begin(), source.end(), predicate), source.end());
remove_copy_if() will only copy the elements NOT matching the predicate, leaving the source vector intact and providing you with the end iterator on the target vector, so that you can shrink it.
// target must be of a size ready to accomodate the copy
target.erase(source.remove_copy_if(source.begin(), source.end(), target.begin(), predicate), target.end());