I would like a wrapper for a std::vector<std::vector<T>> object. Here are a few basic methods implemented under Wrapper
template<class T>
class Wrapper
{
private:
std::vector<std::vector<T>>& data;
int totalSize;
std::vector<int> indicesMap;
public:
Wrapper(std::vector<std::vector<T>>& input):data(input)
{
totalSize = 0;
for (int i = 0 ; i < data.size() ; i++)
{
totalSize += data[i].size();
indicesMap.push_back(totalSize);
}
}
T operator[](int index)
{
int whichVector = std::upper_bound(
indicesMap.begin(),
indicesMap.end(),
index
) - indicesMap.begin();
int i = whichVector == 0 ? index : index - indicesMap[whichVector-1];
return data[whichVector][i];
}
int size()
{
return totalSize;
}
};
Here is a simple test
int main()
{
std::vector<std::vector<int>> x;
std::vector<int> x1 = {1,2,3};
std::vector<int> x2 = {10,20,30};
std::vector<int> x3 = {100,200,300};
x.push_back(x1);
x.push_back(x2);
x.push_back(x3);
Wrapper<int> w(x);
std::cout << w[4] << "\n"; // prints 20 as expected
return 0;
}
I would like to be able to use upper_bound and lower_bound on the object Wrapper. I don't really understand how to make iterators to custom-made objects though and fail to implement that and even then, I am not quite sure it is feasible to just give the being and end iterators to lower_bound.
Can you help me to implement upper_bound and lower_bound for the object Wrapper?
My goal would be to be able to do
std::lower_bound(w.begin(), w.end(), object);
You have to create and implement iterators for your wrapper that satisfy concept ForwardIterator. Details on how to do that can be found in answers to this subject How to correctly implement custom iterators and const_iterators?. Then provide methods of your wrapper that return first and behind the past iterator (usually they called begin() and end() and they better be but you can call them whatever way you want).
Iterator can be implemented as std::pair<size_t,size_t> with positions in data plus reference to data itself with proper implementation of operator++.
Optionally for optimization you may want to make your iterator to satisfy RandomAccessIterator concept and std::lower_bound or std::upper_bound could be more efficient (depends on how you implement random access of course).
Related
I want to build a simple iterator, for example - in the class: "myVector":
#include <iostream>
using namespace std;
#define maxSize 10
class myVector {
private:
int *arr;
int sp;
public:
myVector() {
arr = new int[maxSize];
sp = 0;
}
bool add(int num) {
if (sp==maxSize) return 0;
arr[sp] = num;
sp++;
return 1;
}
};
in the Example - I built a class that produces objects of type myVector. Now I want to build iterator with an operator ++ to run on the private Array of the vector.
thank you very much
You must support std::iterator_traits<YourIterator>. The easy way is to inherit from std::iterator<?> with the appropiate arguments.
In doing so you have to decide on an iterator category. This determines what you guarantee to support, both operator wise and behaviour wise.
Now, boost has some helper types to make writing an iterator a tad easier. Consider using boost. But a basic iterator is not impossible to write without them.
In the particular case above, a pointer is a valid iterator for your problem. And easier than either of the above options. Use this as your first iteration: KISS. Note that pointers have std::iterator_traits support for free.
To make your object iterable (and support for(auto&&x:c) syntax), either write a free begin and end function in the same namespace as your class that produces iterators, or add begin() and end() methods that do the same. I tend to also add size and empty and front and back as I find them useful. As an example:
T& back(){return *std::prev(end());}
T const& back()const{return *std::prev(end());}
You need to write something like this.
class myVector {
class myIterator {
private:
int *position; //operator ++ increment this position
public:
myIterator operator++(){
//increment position here
}
int& operator*(){
//return *pos
}
bool operator==(const myIterator &it)const {
//check that pos and it.pos are the same
}
};
};
This will work but wont be a STL compliant iterator, for that you will also need to add several typedefs, to say for instance the type of your iterator (in your case you have an input iterator). If you want an STL iterator the easiest thing is to use boost facade iterator.
How do I get the position of an element inside a vector, where the elements are classes. Is there a way of doing this?
Example code:
class Object
{
public:
void Destroy()
{
// run some code to get remove self from vector
}
}
In main.cpp:
std::vector<Object> objects;
objects.push_back( <some instances of Object> );
// Some more code pushing back some more stuff
int n = 20;
objects.at(n).Destroy(); // Assuming I pushed back 20 items or more
So I guess I want to be able to write a method or something which is a member of the class which will return the location of itself inside the vector... Is this possible?
EDIT:
Due to confusion, I should explain better.
void Destroy(std::vector<Object>& container){
container.erase( ?...? );
}
The problem is, how can I find the number to do the erasing...? Apparently this isn't possible... I thought it might not be...
You can use std::find to find elements in vector (providing you implement a comparison operator (==) for Object. However, 2 big concerns:
If you need to find elements in a container then you will ger much better performance with using an ordered container such as std::map or std::set (find operations in O(log(N)) vs O(N)
Object should not be the one responsible of removing itself from the container. Object shouldn't know or be concerned with where it is, as that breaks encapsulation. Instead, the owner of the container should concern itself ith such tasks.
The object can erase itself thusly:
void Destroy(std::vector<Object>& container);
{
container.erase(container.begin() + (this - &container[0]));
}
This will work as you expect, but it strikes me as exceptionally bad design. Members should not have knowledge of their containers. They should exist (from their own perspective) in an unidentifiable limbo. Creation and destruction should be left to their creator.
Objects in a vector don't automatically know where they are in the vector.
You could supply each object with that information, but much easier: remove the object from the vector. Its destructor is then run automatically.
Then the objects can be used also in other containers.
Example:
#include <algorithm>
#include <iostream>
#include <vector>
class object_t
{
private:
int id_;
public:
int id() const { return id_; }
~object_t() {}
explicit object_t( int const id ): id_( id ) {}
};
int main()
{
using namespace std;
vector<object_t> objects;
for( int i = 0; i <= 33; ++i )
{
objects.emplace_back( i );
}
int const n = 20;
objects.erase( objects.begin() + n );
for( auto const& o : objects )
{
cout << o.id() << ' ';
}
cout << endl;
}
If you need to destroy the n'th item in a vector then the easiest way is to get an iterator from the beginning using std::begin() and call std::advance() to advance how ever many places you want, so something like:
std::vector<Object> objects;
const size_t n = 20;
auto erase_iter = std::advance(std::begin(objects), n);
objects.erase(erase_iter);
If you want to find the index of an item in a vector then use std::find to get the iterator and call std::distance from the beginning.
So something like:
Object object_to_find;
std::vector<Object> objects;
auto object_iter = std::find(std::begin(objects), std::end(objects), object_to_find);
const size_t n = std::distance(std::begin(objects), object_iter);
This does mean that you need to implement an equality operator for your object. Or you could try something like:
auto object_iter = std::find(std::begin(objects), std::end(objects),
[&object_to_find](const Object& object) -> bool { return &object_to_find == &object; });
Although for this to work the object_to_find needs to be the one from the actual list as it is just comparing addresses.
I have my loop going through vector's elements. While in this loop some of the elements are being (I want them to be) removed. Although std::vector does not allow to do this, and I would like an alternative.
for(unsigned int j = 0; j < rectArray.size(); j++)
{
if( rectArray[j] == 2 )
{
rectArray.erase(rectArray.begin() + j);
}
//...
}
Do you think a std::list would be good here ? Can I use something else ?
Unless the elements of the vector are very expensive to copy, the simplest is probably to std::copy_if (or otherwise copy the ones you want to keep) into a new vector, and then swap that with the original. There's also remove_if followed by resize.
If the elements are very expensive to relocate, then a list would avoid that, but it depends what else you do with the collection. If you do something else that would be cripplingly slow with a list, then you've just moved the problem elsewhere.
I would suggest modifying your code such that it uses iterators instead of the actual vector. It's much cleaner and more efficient like this:
for (auto it = rectArray.begin(); it != rectArray.end(); ++it)
{
// Access the current element with *it
// If you want you can pass `it` and `rectArray.end()` as
// the lower and upper bounds of the new collection,
// rather than doing expensive resizes of the vector.
}
Note that auto is a C++11 feature (the way I used it). If your compiler supports that you might also want to use C++11's foreach:
for (auto it : rectArray) {
// same as before
}
Removing an element from the middle of a vector is expensive - because you have to move all the later elements down.
If you need to add/remove elements to the middle of a container then a list is generally better.
List would be better than a vector - as it will not cost you anything to remove elements from the middle of the list. Removing elements from the middle of a vector, on the other hand, has linear complexity.
Possible alternative to std::remove_if. A bit faster and doesn't require a functor, however it does not maintain order.
auto end = std::end(rectArray);
for(auto it = std::begin(rectArray); it != end; ++it)
{
if(it->remove_me()))
std::swap(*it, *--end); // or even faster *it = std::move(*--end);
}
rectArray.erase(end, std::end(rectArray));
If you are doing a lot of deletes, a list is probably the way to go. Here is some sample code to help.
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
class Widget
{
public:
explicit Widget(int someNumber);
bool ShouldDelete();
bool ShouldDeleteComplex(int a, int b, int c);
private:
int _someNumber;
};
Widget::Widget(int someNumber) : _someNumber(someNumber)
{
}
bool Widget::ShouldDelete()
{
if (_someNumber > 2)
{
return true;
}
return false;
}
bool Widget::ShouldDeleteComplex(int a, int b, int c)
{
if ((a * b - c) > _someNumber)
{
return true;
}
return false;
}
int main()
{
list<Widget> lw;
lw.push_back(Widget(1));
lw.push_back(Widget(2));
lw.push_back(Widget(3));
// delete from list using functor
lw.remove_if(mem_fun_ref(&Widget::ShouldDelete));
// delete from list using lambda function
lw.remove_if([] (Widget& x) { return x.ShouldDeleteComplex(1, 2, 0); } );
vector<Widget> vw;
vw.push_back(Widget(1));
vw.push_back(Widget(2));
vw.push_back(Widget(3));
// delete using functor
vw.erase(remove_if(vw.begin(), vw.end(), mem_fun_ref(&Widget::ShouldDelete)), vw.end());
// delete using lambda function
vw.erase(
remove_if(vw.begin(), vw.end(),
[] (Widget& x) { return x.ShouldDeleteComplex(1, 2, 0); }
),
vw.end());
return 0;
}
I've recently (4 days) started to learn C++ coming from C / Java background. In order to learn a new language I ussualy start by re-implementing different classical algorithms, as language specific as I can.
I've come to this code, its a DFS - Depth First Search in an unoriented graph. Still from what I read it's best to pass parameters by references in C++. Unfortunately I can't quite grasp the concept of reference. Every time I need a reference, I get confused and I think in terms of pointers. In my current code, i use pass by value .
Here is the code (probably isn't Cppthonic as it should):
#include <algorithm>
#include <iostream>
#include <fstream>
#include <string>
#include <stack>
#include <vector>
using namespace std;
template <class T>
void utilShow(T elem);
template <class T>
void utilShow(T elem){
cout << elem << " ";
}
vector< vector<short> > getMatrixFromFile(string fName);
void showMatrix(vector< vector<short> > mat);
vector<unsigned int> DFS(vector< vector<short> > mat);
/* Reads matrix from file (fName) */
vector< vector<short> > getMatrixFromFile(string fName)
{
unsigned int mDim;
ifstream in(fName.c_str());
in >> mDim;
vector< vector<short> > mat(mDim, vector<short>(mDim));
for(int i = 0; i < mDim; ++i) {
for(int j = 0; j < mDim; ++j) {
in >> mat[i][j];
}
}
return mat;
}
/* Output matrix to stdout */
void showMatrix(vector< vector<short> > mat){
vector< vector<short> >::iterator row;
for(row = mat.begin(); row < mat.end(); ++row){
for_each((*row).begin(), (*row).end(), utilShow<short>);
cout << endl;
}
}
/* DFS */
vector<unsigned int> DFS(vector< vector<short> > mat){
// Gives the order for DFS when visiting
stack<unsigned int> nodeStack;
// Tracks the visited nodes
vector<bool> visited(mat.size(), false);
vector<unsigned int> result;
nodeStack.push(0);
visited[0] = true;
while(!nodeStack.empty()) {
unsigned int cIdx = nodeStack.top();
nodeStack.pop();
result.push_back(cIdx);
for(int i = 0; i < mat.size(); ++i) {
if(1 == mat[cIdx][i] && !visited[i]) {
nodeStack.push(i);
visited[i] = true;
}
}
}
return result;
}
int main()
{
vector< vector<short> > mat;
mat = getMatrixFromFile("Ex04.in");
vector<unsigned int> dfsResult = DFS(mat);
cout << "Adjancency Matrix: " << endl;
showMatrix(mat);
cout << endl << "DFS: " << endl;
for_each(dfsResult.begin(), dfsResult.end(), utilShow<unsigned int>);
return (0);
}
Can you please can give me some hints on how to use references, by referencing to this code ?
Is my current programming style, compatible with the constructs of C++ ?
Is there a standard alternative for vector and type** for bi dimensional arrays in C++ ?
LATER EDIT:
OK, I've analyzed your answers (thanks all), and I've rewritten the code in a more OOP manner. Also I've understand what a reference and were to use it. It's somewhat similar to a const pointer, except the fact that a pointer of that type can hold a NULL.
This is my latest code:
#include <algorithm>
#include <fstream>
#include <iostream>
#include <ostream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
template <class T> void showUtil(T elem);
/**
* Wrapper around a graph
**/
template <class T>
class SGraph
{
private:
size_t nodes;
vector<T> pmatrix;
public:
SGraph(): nodes(0), pmatrix(0) { }
SGraph(size_t nodes): nodes(nodes), pmatrix(nodes * nodes) { }
// Initialize graph from file name
SGraph(string &file_name);
void resize(size_t new_size);
void print();
void DFS(vector<size_t> &results, size_t start_node);
// Used to retrieve indexes.
T & operator()(size_t row, size_t col) {
return pmatrix[row * nodes + col];
}
};
template <class T>
SGraph<T>::SGraph(string &file_name)
{
ifstream in(file_name.c_str());
in >> nodes;
pmatrix = vector<T>(nodes * nodes);
for(int i = 0; i < nodes; ++i) {
for(int j = 0; j < nodes; ++j) {
in >> pmatrix[i*nodes+j];
}
}
}
template <class T>
void SGraph<T>::resize(size_t new_size)
{
this->pmatrix.resize(new_size * new_size);
}
template <class T>
void SGraph<T>::print()
{
for(int i = 0; i < nodes; ++i){
cout << pmatrix[i];
if(i % nodes == 0){
cout << endl;
}
}
}
template <class T>
void SGraph<T>::DFS(vector<size_t> &results, size_t start_node)
{
stack<size_t> nodeStack;
vector<bool> visited(nodes * nodes, 0);
nodeStack.push(start_node);
visited[start_node] = true;
while(!nodeStack.empty()){
size_t cIdx = nodeStack.top();
nodeStack.pop();
results.push_back(cIdx);
for(int i = 0; i < nodes; ++i){
if(pmatrix[nodes*cIdx + i] && !visited[i]){
nodeStack.push(i);
visited[i] = 1;
}
}
}
}
template <class T>
void showUtil(T elem){
cout << elem << " ";
}
int main(int argc, char *argv[])
{
string file_name = "Ex04.in";
vector<size_t> dfs_results;
SGraph<short> g(file_name);
g.DFS(dfs_results, 0);
for_each(dfs_results.begin(), dfs_results.end(), showUtil<size_t>);
return (0);
}
For 4 days into C++, you're doing a great job. You're already using standard containers, algorithms, and writing your own function templates. The most sorely lacking thing I see is exactly in reference to your question: the need to pass by reference/const reference.
Any time you pass/return a C++ object by value, you are invoking a deep copy of its contents. This isn't cheap at all, especially for something like your matrix class.
First let's look at showMatrix. The purpose of this function is to output the contents of a matrix. Does it need a copy? No. Does it need to change anything in the matrix? No, it's purpose is just to display it. Thus we want to pass the Matrix by const reference.
typedef vector<short> Row;
typedef vector<Row> SquareMatrix;
void showMatrix(const SquareMatrix& mat);
[Note: I used some typedefs to make this easier to read and write. I recommend it when you have a lot of template parametrization].
Now let's look at getMatrixFromFile:
SquareMatrix getMatrixFromFile(string fName);
Returning SquareMatrix by value here could be expensive (depending on whether your compiler applies return value optimization to this case), and so is passing in a string by value. With C++0x, we have rvalue references to make it so we don't have to return a copy (I also modified the string to be passed in by const reference for same reasons as showMatrix, we don't need a copy of the file name):
SquareMatrix&& getMatrixFromFile(const string& fName);
However, if you don't have a compiler with these features, then a common compromise is to pass in a matrix by reference and let the function fill it in:
void getMatrixFromFile(const string& fName, SquareMatrix& out_matrix);
This doesn't give provide as convenient a syntax for the client (now they have to write two lines of code instead of one), but it avoids the deep copying overhead consistently. There is also MOJO to address this, but that will become obsolete with C++0x.
A simple rule of thumb: if you have any user-defined type (not a plain old data type) and you want to pass it to a function:
pass by const reference if the function only needs to read from it.
pass by reference if the function needs to modify the original.
pass by value only if the function needs a copy to modify.
There are exceptions where you might have a cheap UDT (user-defined type) that is cheaper to copy than it is to pass by const reference, e.g., but stick to this rule for now and you'll be on your way to writing safe, efficient C++ code that doesn't waste precious clock cycles on unnecessary copies (a common bane of poorly written C++ programs).
To pass by reference, you'd typically change this:
vector<unsigned int> DFS(vector< vector<short> > mat){
to:
vector<unsigned int> DFS(vector<vector<short>> const &mat) {
Technically, this is passing a const reference, but that's what you normally want to use when/if you're not planning to modify the original object.
On another note, I'd probably change this:
for_each((*row).begin(), (*row).end(), utilShow<short>);
to something like:
std::copy(row->begin(), row->end(), std::ostream_iterator<short>(std::cout, " "));
Likewise:
for_each(dfsResult.begin(), dfsResult.end(), utilShow<unsigned int>);
would become:
std::copy(dfsResult.begin(), dfsResult.end(),
std::ostream_iterator<unsigned int>(std::cout, " "));
(...which looks like it would obviate utilShow entirely).
As far as 2D matrices go, unless you need a ragged matrix (where different rows can be different lengths), you typically use a simple front-end to handle indexing in a single vector:
template <class T>
class matrix {
std::vector<T> data_;
size_t columns_;
public:
matrix(size_t rows, size_t columns) : columns_(columns), data_(rows * columns) {}
T &operator()(size_t row, size_t column) { return data[row * columns_ + column]; }
};
Note that this uses operator() for indexing, so instead of m[x][y], you'd use m(x,y), about like in BASIC or Fortran. You can overload operator[] in a way that allows you to use that notation if you prefer, but it's a fair amount of extra work with (IMO) little real benefit.
References and pointers are closely related. Both are ways of passing parameters without copying the parameter value onto the subroutine's stack frame.
The main difference between them:
A pointer p points to an object o.
A reference i is an object o. In other words, in an alias.
To make things more confusing, as far as I know, the compiler implementation between the two is pretty much the same.
Imagine the function Ptr(const T* t) and Ref(const T& t).
int main() {
int a;
Ptr(&a);
Ref(a);
}
In Ptr, t is going to point to the location of a. You can dereference it and get the value of a. If you do &t (take the address of t), you will get the address of the parameter.
In Ref, t is a. You can use a for the value of a. You can get the address of a with &a. It's a little syntactic sugar that c++ gives you.
Both provide a mechanism for passing parameters without copying. In your function (by the way, you don't need the declaration):
template <class T> void utilShow(T elem) { ... }
Every time it gets called, T will be copied. If T is a large vector, it is copying all the data in the vector. That's pretty inefficient. You don't want to pass the entire vector to the new stack frame, you want to say "hey - new stack frame, use this data". So you can pass by reference. What does that look like?
template <class T> void utilShow(const T &elem) { ... }
elem is const, because it's not changed by the function. It's also going to use the memory for elem that's stored in the caller, rather than copying it down the stack.
Again, for the same reason (to avoid a copy of the parameters), use:
vector< vector<short> > getMatrixFromFile(const string &fName) { ... }
void showMatrix(const vector< vector<short> > &mat) { ... }
The one tricky part is that you might think: "Hey, a reference means no copies! I'm gonna use it all the time! I'm gonna return references from functions!" And that's where your program crashes.
Imagine this:
// Don't do this!
Foo& BrokenReturnRef() {
Foo f;
return f;
}
int main() {
Foo &f = BrokenReturnRef();
cout << f.bar();
}
Unfortunately, this is broken! When BrokenReturnRef runs, f is in scope and everything is cool. Then you return to main and keep referencing f. The stack frame that created f has gone away, and that location is no longer valid, and you're referencing junk memory. In this case, you'll have to return by value (or allocate a new pointer on the heap).
The one exception to the rule of "don't return references" is when you know that memory will outlast the stack. This is how STL implements operator[] for its containers.
Hope that helps! :)
void utilShow(T& elem);
vector< vector<short> > getMatrixFromFile(const string& fName);
void showMatrix(vector< vector<short> >& mat);
vector<unsigned int> DFS(vector< vector<short> >& mat);
Some which I could figure out. And if possible if you aren't changing or intend to change the state of the object inside your method body make the variables passed as const.
I wouldn't ask you include all the C++ constructs in your first try itself, but gradually so that you don't overwhelm yourself to depression. Vector is the most used STL container. And usage of containers depend on your needs rather than feeling fanciful to use one over another.
One brief description of containers.
http://msdn.microsoft.com/en-us/library/1fe2x6kt%28VS.80%29.aspx
#Jerry Thanks for editing.
Vector isn't overused, but is used more because of its simplicity for simple objects, rather than large monolithic class objects. It resembles a C style array, but isn't, with a lot of extra algorithms. Two more which are used quite frequently are maps and lists. It maybe so because of the places where I work they need the use of these containers more than at other places.
Suppose I have the following two data structures:
std::vector<int> all_items;
std::set<int> bad_items;
The all_items vector contains all known items and the bad_items vector contains a list of bad items. These two data structures are populated entirely independent of one another.
What's the proper way to write a method that will return a std::vector<int> contain all elements of all_items not in bad_items?
Currently, I have a clunky solution that I think can be done more concisely. My understanding of STL function adapters is lacking. Hence the question. My current solution is:
struct is_item_bad {
std::set<int> const* bad_items;
bool operator() (int const i) const {
return bad_items.count(i) > 0;
}
};
std::vector<int> items() const {
is_item_bad iib = { &bad_items; };
std::vector<int> good_items(all_items.size());
std::remove_copy_if(all_items.begin(), all_items.end(),
good_items.begin(), is_item_bad);
return good_items;
}
Assume all_items, bad_items, is_item_bad and items() are all a part of some containing class. Is there a way to write them items() getter such that:
It doesn't need temporary variables in the method?
It doesn't need the custom functor, struct is_item_bad?
I had hoped to just use the count method on std::set as a functor, but I haven't been able to divine the right way to express that w/ the remove_copy_if algorithm.
EDIT: Fixed the logic error in items(). The actual code didn't have the problem, it was a transcription error.
EDIT: I have accepted a solution that doesn't use std::set_difference since it is more general and will work even if the std::vector isn't sorted. I chose to use the C++0x lambda expression syntax in my code. My final items() method looks like this:
std::vector<int> items() const {
std::vector<int> good_items;
good_items.reserve(all_items.size());
std::remove_copy_if(all_items.begin(), all_items.end(),
std::back_inserter(good_items),
[&bad_items] (int const i) {
return bad_items.count(i) == 1;
});
}
On a vector of about 8 million items the above method runs in 3.1s. I bench marked the std::set_difference approach and it ran in approximately 2.1s. Thanks to everyone who supplied great answers.
As jeffamaphone suggested, if you can sort any input vectors, you can use std::set_difference which is efficient and less code:
#include <algorithm>
#include <set>
#include <vector>
std::vector<int>
get_good_items( std::vector<int> const & all_items,
std::set<int> const & bad_items )
{
std::vector<int> good_items;
// Assumes all_items is sorted.
std::set_difference( all_items.begin(),
all_items.end(),
bad_items.begin(),
bad_items.end(),
std::back_inserter( good_items ) );
return good_items;
}
Since your function is going to return a vector, you will have to make a new vector (i.e. copy elements) in any case. In which case, std::remove_copy_if is fine, but you should use it correctly:
#include <iostream>
#include <vector>
#include <set>
#include <iterator>
#include <algorithm>
#include <functional>
std::vector<int> filter(const std::vector<int>& all, const std::set<int>& bad)
{
std::vector<int> result;
remove_copy_if(all.begin(), all.end(), back_inserter(result),
[&bad](int i){return bad.count(i)==1;});
return result;
}
int main()
{
std::vector<int> all_items = {4,5,2,3,4,8,7,56,4,2,2,2,3};
std::set<int> bad_items = {2,8,4};
std::vector<int> filtered_items = filter(all_items, bad_items);
copy(filtered_items.begin(), filtered_items.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
To do this in C++98, I guess you could use mem_fun_ref and bind1st to turn set::count into a functor in-line, but there are issues with that (which resulted in deprecation of bind1st in C++0x) which means depending on your compiler, you might end up using std::tr1::bind anyway:
remove_copy_if(all.begin(), all.end(), back_inserter(result),
bind(&std::set<int>::count, bad, std::tr1::placeholders::_1)); // or std::placeholders in C++0x
and in any case, an explicit function object would be more readable, I think:
struct IsMemberOf {
const std::set<int>& bad;
IsMemberOf(const std::set<int>& b) : bad(b) {}
bool operator()(int i) const { return bad.count(i)==1;}
};
std::vector<int> filter(const std::vector<int>& all, const std::set<int>& bad)
{
std::vector<int> result;
remove_copy_if(all.begin(), all.end(), back_inserter(result), IsMemberOf(bad));
return result;
}
At the risk of appearing archaic:
std::set<int> badItems;
std::vector<int> items;
std::vector<int> goodItems;
for ( std::vector<int>::iterator iter = items.begin();
iter != items.end();
++iter)
{
int& item = *iter;
if ( badItems.find(item) == badItems.end() )
{
goodItems.push_back(item);
}
}
std::remove_copy_if returns an iterator to the target collection. In this case, it would return good_items.end() (or something similar). good_items goes out of scope at the end of the method, so this would cause some memory errors. You should return good_items or pass in a new vector<int> by reference and then clear, resize, and populate it. This would get rid of the temporary variable.
I believe you have to define the custom functor because the method depends on the object bad_items which you couldn't specify without it getting hackey AFAIK.