insert object into a set - c++

I want to insert a vector into a set like this:
set<vector<prmEdge> > cammini;
vector<prmEdge> vecEdge;
cammini.insert(vecEdge);
I have a compilation error like this:
prmPlanner.cpp:1285: instantiated from here
/usr/include/c++/4.2/bits/stl_algobase.h:853: error: no match for ‘operator<’ in ‘__first1.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = const prmEdge*, _Container = std::vector<prmEdge, std::allocator<prmEdge> >]() < __first2.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = const prmEdge*, _Container = std::vector<prmEdge, std::allocator<prmEdge> >]()’
/usr/include/c++/4.2/bits/stl_algobase.h:855: error: no match for ‘operator<’ in ‘__first2.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = const prmEdge*, _Container = std::vector<prmEdge, std::allocator<prmEdge> >]() < __first1.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = const prmEdge*, _Container = std::vector<prmEdge, std::allocator<prmEdge> >]()’
make[1]: *** [prmPlanner.o] Errore 1
What should I do?
Could somebody help me??
Thank you very much

It doesn't know how to compare vectors. You should supply operator< for vector<prmEdge> (or for prmEdge to automatically use std::lexicographical_compare for vectors) or use unordered_set if you don't actually need sorted set of vectors.

Since the elements in your set are vectors, which don't define operator<, you'll need to do one of two things: write a wrapper around vector that defines operator<, or else write a comparison functor, and supply it as a parameter when you create your set.

The object contained in the set must have operator < defined.

std::set needs its entries to be sortable. The std::vector is however not sortable.

std::set needs a predicate to sort elements. By default that's <, so you would need to define operator < for vector<prmEdge>. You can supply a custom predicate to std::set as well, see here.

agree with previous answers, just want to add that you can create global bool operator<(vector<T> v)

Related

Remove duplicate vectors from vector of vectors

I am trying to implement the solution to the problem found at Link.
Here is my snippet of code
bool compareVec(vector<int> a, vector<int> b) {
return std::equal(a.begin(), a.end(), b.begin());
}
vector<vector<int> > ans;
ans.erase(std::remove_if(ans.begin(), ans.end(), compareVec), ans.end());
I am getting the following errors
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of
'_RandomAccessIterator std::__find_if(_RandomAccessIterator,
_RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with
_RandomAccessIterator = __gnu_cxx::__normal_iterator<std::vector<int>*,
std::vector<std::vector<int> > >; _Predicate = bool (*)(std::vector<int>,
std::vector<int>)]':
/usr/include/c++/4.8/bits/stl_algo.h:4465:41: required from '_IIter
std::find_if(_IIter, _IIter, _Predicate) [with _IIter =
__gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>
> >; _Predicate = bool (*)(std::vector<int>, std::vector<int>)]'
/usr/include/c++/4.8/bits/stl_algo.h:1144:64: required from '_FIter
std::remove_if(_FIter, _FIter, _Predicate) [with _FIter =
__gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>
> >; _Predicate = bool (*)(std::vector<int>, std::vector<int>)]'
solution.cpp:40:64: required from here
/usr/include/c++/4.8/bits/stl_algo.h:214:23: error: too few arguments to
function
if (__pred(*__first))
^
/usr/include/c++/4.8/bits/stl_algo.h:218:23: error: too few arguments to
function
if (__pred(*__first))
^
/usr/include/c++/4.8/bits/stl_algo.h:222:23: error: too few arguments to
function
if (__pred(*__first))
^
Can anyone help me out in debugging this?
Thanks in advance
EDIT
The elements of vector are sorted and all these vectors are also sorted.
Unique also gives an error. I am unable to figure out why?
Why is the example given in the link I provided, not helpful here?
std::remove_if requires a unary predicate. You pass a binary predicate, which causes your errors (/usr/include/c++/4.8/bits/stl_algo.h:222:23: error: too few arguments to function → your function takes two arguments, not one).
Further, std::remove_if does its removals with no consideration of other elements (which is why it accepts a unary predicate), so it isn't actually what you're looking for.
What you want to use is std::unique, which does require the compareVec you've implemented. However, std::vector already provides the operator== overload, so that implementation is actually redundant! Also, you say that you get an error when using std::unique. Try passing your parameters as const&.
Thus, when your outer vector and inner vectors are already sorted, the solution is as it'd be for any other vector of sorted elements:
outer.erase(std::unique(outer.begin(), outer.end()), outer.end());
Okay, since this is not marked with C++11, I will use a functor instead of a lambda.
The first problem you have is that remove_if takes a UnaryPredicate, which means it should only accept a single argument.
The second issue is also related to your understanding of remove_if. After you fix compareVec to only accept one argument, you're left wondering how you could possibly compare all elements against each other.
You could approach this one of two ways:
Sort your vector of vectors (< operator is defined lexicographically for vector) and then use std::unique (Examples) (More examples).
In the link you provided (same as the one I just linked to), notice that they sort first, and you do not.
Or, if there's no clear definition of < for your elements, only ==, you could perform an O(N2) lookup/erase on each subsequent item (shown below):
Comparison functor (could make as a lambda in C++11 and greater)
struct CompareVec
{
CompareVec(const std::vector<int>& _in) : compare_against(_in){}
bool operator()(const std::vector<int>& rhs) const
{
return compare_against == rhs;
};
const std::vector<int>& compare_against;
};
To be used like so:
for (size_t i = 0; i < ans.size(); ++i)
{
CompareVec comparator(ans[i]);
ans.erase(std::remove_if(ans.begin()+i+1, ans.end(), comparator), ans.end());
}
Live Demo (Compiled in C++11 for want of initializing test vectors with initializer lists)
Edit
In C++11 we can get rid of the CompareVec functor and replace it with a lambda:
for (size_t i = 0; i < ans.size(); ++i)
{
ans.erase(std::remove_if(ans.begin()+i+1, ans.end(),
[&ans, &i](const std::vector<int>& _rhs)
{
return ans[i] == _rhs;
}) , ans.end());
}
Demo2

make_heap on std::map with user defined comparison & random access iterator

I have a map defined like this
std::map<int,int> myMap;
After processing this map I want to treat it as a heap (based on the second value). I decided to use std::make_heap function.. which is defined like this...
template< class RandomIt, class Compare > void make_heap( RandomIt first, RandomIt last, Compare comp );
As this function requires a comparison function to be defined... I did it like this
bool compare(const std::pair<int,int> &frst, const std::pair<int,int> &scnd)
Now with this setup I call make_heap like this
std::make_heap(myMap.begin(), myMap.end(),compare);
But this gives me compilation error...
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h: In function ‘void std::make_heap(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = std::_Rb_tree_iterator<std::pair<const int, int> >]’:
maxRepeatingNumber.cc:48: instantiated from here /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:357: error: no match for ‘operator-’ in ‘__last - __first’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include e/c++/4.1.2/bits/stl_bvector.h:182: note: candidates are: ptrdiff_t std::operator-(const std::_Bit_iterator_base&, const std::_Bit_iterator_base&)
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/ c++/4.1.2/bits/stl_heap.h:360: error: no match for ‘operator-’ in ‘__last - __first’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_bvector.h:182: note: candidates are: ptrdiff_t std::operator-(const std::_Bit_iterator_base&, const std::_Bit_iterator_base&)
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:364: error: no match for ‘operator+’ in ‘__first + __parent’
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_bvector.h:267: note: candidates are: std::_Bit_iterator std::operator+(ptrdiff_t, const std::_Bit_iterator&)
Compilation error gives me a hint that they may be because of make_heap requires random_access_iterator... but I am not sure on that.
Should I move to Function Objects (from plain function pointer)?
Any help?
You cannot make a heap directly on a map. Map is sorted already by a key and you need a different partial sorting. You can copy all map values to a vector and make a heap from it.
Edit:
If you need to modify your map and maintain the heap, you can implement something like multi-index container when one of indexes would be actually heap-powered.
Agreed with #Andy. Map is already sorted by key so you can't make heap directly on it. To solve similar problem i created a vector of pair with map value as first element and key as second element and then make heap. It won't require any compactor parameter for max heap.
For example: For map "map m" create vector using below code and then make heap.
for(it=m.begin(); it != m.end(); it++)
v.push_back(make_pair(it->second,it->first));
make_heap(v.begin(),v.end(),sort_v());
This will work and top element would be returned at any point of time.

what does the error mean when I am compiling c++ with g++ compiler?

using the following code:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> ivec;
for(vector<int>::size_type ix = 0; ix != 10; ix++)
{
ivec.push_back(ix);
}
vector<int>::iterator mid = (ivec.begin() + ivec.end()) / 2;
cout << *mid << endl;
return 0;
}
I get an error compiling with g++:
iterator_io.cpp: In function `int main()':
iterator_io.cpp:13: error: no match for 'operator+' in '(&ivec)->std::vector<_Tp, _Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>]() + (&ivec)->std::vector<_Tp, _Alloc>::end [with _Tp = int, _Alloc = std::allocator<int>]()'
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_iterator.h:654: note: candidates are: __gnu_cxx::__normal_iterator<_Iterator, _Container> __gnu_cxx::__normal_iterator<_Iterator, _Container>::operator+(const typename std::iterator_traits<_Iterator>::difference_type&) const [with _Iterator = int*, _Container = std::vector<int, std::allocator<int> >]
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_bvector.h:261: note: std::_Bit_iterator std::operator+(ptrdiff_t, const std::_Bit_iterator&)
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_bvector.h:345: note: std::_Bit_const_iterator std::operator+(ptrdiff_t, const std::_Bit_const_iterator&)
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_iterator.h:765: note: __gnu_cxx::__normal_iterator<_Iterator, _Container> __gnu_cxx::operator+(typename __gnu_cxx::__normal_iterator<_Iterator, _Container>::difference_type, const __gnu_cxx::__normal_iterator<_Iterator, _Container>&) [with _Iterator = int*, _Container = std::vector<int, std::allocator<int> >]
I know the ivec.end() can not be used as a normal vector element. But I can't understand what the error information means...something about operator+?
You cannot add two iterators together.
operator+ is not defined for two iterators, because that operation wouldn't make sense. Iterators are a kind of generalization over pointers - they point to the specific element stored in container. At which element the sum of iterators is pointing?
However, when you use a vector, you can add integers to iterators, like that:
vec.begin() + vec.size() / 2
and that is why you have candidates are: (...) in your error message, followed by some definitions of operator+.
In your case the best, and cleanest way will be not using the iterators, but simple getting the value from specified position:
int mid = vec[vec.size() / 2];
You cannot add iterators. What you can do:
vector<int>::iterator mid = ivec.begin() + distance(ivec.begin(), ivec.end()) / 2;
It simply means that vector iterators have no addition operator (+). You cannot add ivec.begin() and ivec.end().
To get the middle element, you can simply use the subscript operator:
cout << ivec[ivec.size()/2] << endl;
If you insist on using an iterator, you can get an iterator that points to the middle in this fashion:
vector<int>::iterator mid = ivec.begin();
mid += ivec.size()/2;
cout << *mid << endl;
You can do this, because the vector iterator is a random access iterator (in all implementations I'm aware of it encapsulates an actual pointer to the raw container-data).
You can't add iterators.
What you'll want to use is a combination of std::distance() and std::advance():
vector<int>::iterator mid = std::advance(ivec.begin(), std::distance(ivec.begin(), ivec.end()) / 2);
Why use std::advance() instead of the iterator's addition operator? std::advance() works optimally regardless of the iterator type (random access, forward only, bidirectional, etc), so if you switch from std::vector to std::list the above code can remain the same, and still work optimally.
not possible to add two iterators
use at to get the middle item:
ivec.at(ivec.size()/2);
You can not add two iterators together, because iterators are not integers. That's what the error message means. If you want to access the element in the middle of a vector, use ivec[ivec.size() / 2].

Iterator for a container of a custom object

If I've built a class that I want to contain inside, for example a set, how would I iterate through said set? Could I say
std::set<customObject>::iterator it
I thought I could do that, but I'm getting the following series of errors...
drawing.h:110: error: no match for ‘operator=’ in ‘it = ((object*)this)->object::objects. std::vector<_Tp, _Alloc>::begin [with _Tp = object, _Alloc = std::allocator<object>]()’
/usr/include/c++/4.2.1/bits/stl_tree.h:225: note: candidates are: std::_Rb_tree_const_iterator<object>& std::_Rb_tree_const_iterator<object>::operator=(const std::_Rb_tree_const_iterator<object>&)
drawing.h:110: error: no match for ‘operator!=’ in ‘it != ((object*)this)->object::objects. std::vector<_Tp, _Alloc>::end [with _Tp = object, _Alloc = std::allocator<object>]()’
/usr/include/c++/4.2.1/bits/stl_tree.h:292: note: candidates are: bool std::_Rb_tree_const_iterator<_Tp>::operator!=(const std::_Rb_tree_const_iterator<_Tp>&) const [with _Tp = object]
drawing.h:111: error: ‘struct std::_Rb_tree_const_iterator<object>’ has no member named ‘sketch’
here's my code:
void draw_in_place()
{
place();
std::set<object>::const_iterator it;
for(it = objects.begin(); it != objects.end(); it++){
*it.draw_in_place();
}
}
((object*)this)->object::objects. std::vector<_Tp, _Alloc>::begin
objects is apparently a std::vector<object>, not a std::set<object>. You therefore need to use a std::vector<object>::const_iterator.
*it.draw_in_place();
This is incorrect: you need to dereference the iterator to access the element first, then use the element:
(*it).draw_in_place();
// or
it->draw_in_place();
I think (at least) one of your problems is this line:
*it.draw_in_place();
The compiler is interpreting this as
*(it.draw_in_place());
versus your intended
(*it).draw_in_place();
To fix this, consider using the arrow operator, as in
it->draw_in_place();
It's perfectly legal to store custom objects in an STL set, so long as they can be compared with the < operator by default. If they can't, you'll either need to define operator < on them, or provide a custom comparator to the set, or specialize std::less for your particular type.

C++: binary search compile error

I have the following lines of code:
if(std::binary_search(face_verts.begin(), face_verts.end(), left_right_vert[0]) &&
std::binary_search(face_verts.begin(), face_verts.end(), left_right_vert[1]))
And when I compile my code, I get the following errors:
In file included from /usr/include/c++/4.4/algorithm:62,
from R3Mesh.cpp:10:
/usr/include/c++/4.4/bits/stl_algo.h: In function ‘bool std::binary_search(_FIter, _FIter, const _Tp&) [with _FIter = __gnu_cxx::__normal_iterator<R3Point*, std::vector<R3Point, std::allocator<R3Point> > >, _Tp = R3Point]’:
R3Mesh.cpp:1335: instantiated from here
/usr/include/c++/4.4/bits/stl_algo.h:2762: error: no match for ‘operator<’ in ‘__val < __i.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = R3Point*, _Container = std::vector<R3Point, std::allocator<R3Point> >]()’
/usr/include/c++/4.4/bits/stl_algo.h: In function ‘_FIter std::lower_bound(_FIter, _FIter, const _Tp&) [with _FIter = __gnu_cxx::__normal_iterator<R3Point*, std::vector<R3Point, std::allocator<R3Point> > >, _Tp = R3Point]’:
/usr/include/c++/4.4/bits/stl_algo.h:2761: instantiated from ‘bool std::binary_search(_FIter, _FIter, const _Tp&) [with _FIter = __gnu_cxx::__normal_iterator<R3Point*, std::vector<R3Point, std::allocator<R3Point> > >, _Tp = R3Point]’
R3Mesh.cpp:1335: instantiated from here
/usr/include/c++/4.4/bits/stl_algo.h:2442: error: no match for ‘operator<’ in ‘__middle.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = R3Point*, _Container = std::vector<R3Point, std::allocator<R3Point> >]() < __val’
make: *** [R3Mesh.o] Error 1
I did #include <algorithm> in the beginning of the file and I can't seem to figure out the error. The following are the containers used in the function call:
vector <R3Point > face_verts;
vector <R3Point > left_right_vert;
Thanks.
In order to use binary search, your items must be comparable. R3Point doesn't have built-in comparison, that's the core reason.
Moreover, for using binary_search your list must be already sorted wrt the comparison operation.
You need to implement an operator < for your R3Point class. The binary_search() function will use this operator to determine how to find the target item.
std::binary_search uses a predicate function to compare entries. That's operator < by default, so you need to overload this op for R3Point.
Keep in mind that the input range must be ordered by this op for std::binary_search to work properly (well, that's the nature of a binary search).
See http://www.sgi.com/tech/stl/binary_search.html.
In order to use binary_search you input siquence must be sorted in accordance with certain comparison predicate. Later, this very same comparison predicate must be given (explicitly or implicitly) to binary_search to be used during searching.
So, the questions you should answer in this case are the following
Is the input sequence sorted? If it is not, you can stop right here. binary_search cannot be used with unordered sequences.
If it is sorted, then what comparison predicate was used to sort it? And how was it passed to the sorting function?
Once you know the comparison predicate and the passing approach, you can do the same with binary_search.
Note, that the comparison is not necessarily implemented through the operator <, as other answers might suggest. It could be a standalone functor-based comparison predicate, for example. Moreover, the fact that binary_search did not pick up the comparison predicate automatically (as would be the case with operator <) suggests the "standalone" approach.
If the R3Point is implemented by you, then you can add operator< for it.
Otherwise, you must implement a comparison functor, and assign it to binary_search.
Remember the following mark:
Returns true if an element in the range [first,last) is equivalent to value, and false otherwise.