Erase element of struct vector - c++

I am trying to delete a Team Roster element from the playerRoster vector given a user defined jersey number. The problem I am running into is the .erase function isn't working.
struct TeamRoster {
int jerseyNumber;
int playerRating;
};
int numPlayers = 5;
int searchValue = 0;
vector<TeamRoster> playerRoster(numPlayers);
TeamRoster newPlayer;
unsigned int i = 0;
cout << "Enter a jersey number: ";
cin >> searchValue;
cout << endl;
for (i = 0; i < playerRoster.size(); ++i) {
if (playerRoster.at(i).jerseyNumber == searchValue) {
playerRoster.erase(i);
}
}
I am getting this error.
main.cpp: In function 'int main()':
main.cpp:68:36: error: no matching function for call to 'std::vector<main()::TeamRoster>::erase(unsigned int&)'
playerRoster.erase(i);
^
In file included from /usr/include/c++/6/vector:64:0,
from main.cpp:2:
/usr/include/c++/6/bits/stl_vector.h:1147:7: note: candidate: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::const_iterator) [with _Tp = main()::TeamRoster; _Alloc = std::allocator<main()::TeamRoster>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<main()::TeamRoster*, std::vector<main()::TeamRoster> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = main()::TeamRoster*; std::vector<_Tp, _Alloc>::const_iterator = __gnu_cxx::__normal_iterator<const main()::TeamRoster*, std::vector<main()::TeamRoster> >; typename __gnu_cxx::__alloc_traits<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type>::const_pointer = const main()::TeamRoster*]
erase(const_iterator __position)
^~~~~
/usr/include/c++/6/bits/stl_vector.h:1147:7: note: no known conversion for argument 1 from 'unsigned int' to 'std::vector<main()::TeamRoster>::const_iterator {aka __gnu_cxx::__normal_iterator<const main()::TeamRoster*, std::vector<main()::TeamRoster> >}'
/usr/include/c++/6/bits/stl_vector.h:1174:7: note: candidate: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::const_iterator, std::vector<_Tp, _Alloc>::const_iterator) [with _Tp = main()::TeamRoster; _Alloc = std::allocator<main()::TeamRoster>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<main()::TeamRoster*, std::vector<main()::TeamRoster> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = main()::TeamRoster*; std::vector<_Tp, _Alloc>::const_iterator = __gnu_cxx::__normal_iterator<const main()::TeamRoster*, std::vector<main()::TeamRoster> >; typename __gnu_cxx::__alloc_traits<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type>::const_pointer = const main()::TeamRoster*]
erase(const_iterator __first, const_iterator __last)
^~~~~
/usr/include/c++/6/bits/stl_vector.h:1174:7: note: candidate expects 2 arguments, 1 provided
I looked on cplusplus.com and noticed a difference between c++94 and c++11 iterator erase (const_iterator position); (11), iterator erase (iterator position); (94). From the error I'm getting, it looks like my compiler is using c++11.
Does const_iterator mean that I have to use a constant with the .erase() function, and if so, is there a different function that will work in this case?
If this isn't the problem, can you help me figure out what is?

If only one element you want to erase, you could try code below:
for(auto iter = playerRoster.begin(); iter != playerRoster.end(); ++iter){
if(iter->jerseyNumber == searchValue){
iter = playerRoster.erase(iter);
break;
}
}
Or if you want to erase all element that match, you could try :
for(auto iter = playerRoster.begin(); iter != playerRoster.end(); ){
if(iter->jerseyNumber == searchValue){
iter = playerRoster.erase(iter);
}else{
++iter;
}
}
Remember erase return the element after the one that be erased.
Sample code can be found : http://www.cplusplus.com/reference/vector/vector/erase/

Related

Using set in c++ standard template library (STL)

Sets are the collection. There is a function in set isinsert().
It's return type : it returns the iterator pointing to the inserted element in the collection.
I write a code and its working :
#include<bits/stdc++.h>
using namespace std;
int main(){
set<int> s;
s.insert (1);
s.insert (4);
s.insert (2);
s.insert (5);
s.insert (3);
cout << "The elements in set are: ";
for (auto it = s.begin(); it!= s.end (); it++)
cout << *it;
return 0;
}
I write another code and it also working:
#include<bits/stdc++.h>
using namespace std;
int main(){
set<int> s;
auto itr=s.insert (s.begin(),5);
itr=s.insert (itr,4);
itr=s.insert (itr,2);
cout << "The elements in set are: ";
for (auto it = s.begin(); it!= s.end (); it++)
cout << *it;
return 0;
}
Now i merge the logic of both my previous code but now its not working why? :
#include<bits/stdc++.h>
using namespace std;
int main(){
set<int> s;
auto itr=s.insert (1);
s.insert (itr,4);
cout << "The elements in set are: ";
for (auto it = s.begin(); it!= s.end (); it++)
cout << *it;
return 0;
}
Output in above code :
/usr/include/c++/7/bits/stl_set.h:536:7: note: candidate: std::set<_Key, _Compare, _Alloc>::iterator std::set<_Key, _Compare, _Alloc>::insert(std::set<_Key, _Compare, _Alloc>::const_iterator, const value_type&) [with _Key = int; _Compare = std::less<int>; _Alloc = std::allocator<int>; std::set<_Key, _Compare, _Alloc>::iterator = std::_Rb_tree_const_iterator<int>; std::set<_Key, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<int>; std::set<_Key, _Compare, _Alloc>::value_type = int]
insert(const_iterator __position, const value_type& __x)
^~~~~~
/usr/include/c++/7/bits/stl_set.h:536:7: note: no known conversion for argument 1 from ‘std::pair<std::_Rb_tree_const_iterator<int>, bool>’ to ‘std::set<int>::const_iterator {aka std::_Rb_tree_const_iterator<int>}’
/usr/include/c++/7/bits/stl_set.h:541:7: note: candidate: std::set<_Key, _Compare, _Alloc>::iterator std::set<_Key, _Compare, _Alloc>::insert(std::set<_Key, _Compare, _Alloc>::const_iterator, std::set<_Key, _Compare, _Alloc>::value_type&&) [with _Key = int; _Compare = std::less<int>; _Alloc = std::allocator<int>; std::set<_Key, _Compare, _Alloc>::iterator = std::_Rb_tree_const_iterator<int>; std::set<_Key, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<int>; std::set<_Key, _Compare, _Alloc>::value_type = int]
insert(const_iterator __position, value_type&& __x)
^~~~~~
/usr/include/c++/7/bits/stl_set.h:541:7: note: no known conversion for argument 1 from ‘std::pair<std::_Rb_tree_const_iterator<int>, bool>’ to ‘std::set<int>::const_iterator {aka std::_Rb_tree_const_iterator<int>}’
/usr/include/c++/7/bits/stl_set.h:556:2: note: candidate: template<class _InputIterator> void std::set<_Key, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _InputIterator = _InputIterator; _Key = int; _Compare = std::less<int>; _Alloc = std::allocator<int>]
insert(_InputIterator __first, _InputIterator __last)
^~~~~~
/usr/include/c++/7/bits/stl_set.h:556:2: note: template argument deduction/substitution failed:
yo.cpp:14:16: note: deduced conflicting types for parameter ‘_InputIterator’ (‘std::pair<std::_Rb_tree_const_iterator<int>, bool>’ and ‘int’)
s.insert (itr,4)
^
In file included from /usr/include/c++/7/set:61:0,
from /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h:87,
from yo.cpp:1:
/usr/include/c++/7/bits/stl_set.h:568:7: note: candidate: void std::set<_Key, _Compare, _Alloc>::insert(std::initializer_list<_Tp>) [with _Key = int; _Compare = std::less<int>; _Alloc = std::allocator<int>]
insert(initializer_list<value_type> __l)
^~~~~~
/usr/include/c++/7/bits/stl_set.h:568:7: note: candidate expects 1 argument, 2 provided
When you use the syntax:
auto itr = s.insert(5);
The return type of s.insert() with the parameter 5 gives a type of:
std::pair<std::set<int>::iterator, bool>
But there's no such known overloaded conversion from that type to std::set<int>::iterator in the syntax:
itr = s.insert(itr, 4); // error!
_______________^^^_____
To solve it, you need to declare itr correctly:
auto itr = s.insert(s.begin(), 5);
Rather than only:
auto itr = s.insert(5);
In the correct case, the return type of s.insert() is std::set<int>::iterator which is compatible for the next statements.

Usage of multimap with next_permutation c++

i am just trying to implement Knapsack Problem in a Naive way to stress test my original solution.
MY CODE
double StressTest(multimap<int, int> ValWt, int KnapscakWeight)
{
vector<double> TotalValue;
double Temp_KnapsackWeight = 0.0;
double Value = 0.0;
multimap<int, int>::iterator itr1;// = ValWt.begin();
do
{
itr1 = ValWt.begin();
Temp_KnapsackWeight = KnapscakWeight;
while( (Temp_KnapsackWeight > 0) && (itr1 != ValWt.end()) )
{
if(itr1->second > Temp_KnapsackWeight)
{
Value += ( (Temp_KnapsackWeight/itr1->second) * itr1->first );
Temp_KnapsackWeight = 0;
}
else
{
Temp_KnapsackWeight -= itr1->second;
Value += itr1->first;
}
itr1++;
}
TotalValue.push_back(Value);
Value = 0.0;
}while( next_permutation(ValWt.begin(), ValWt.end()) );
return *max_element(TotalValue.begin(), TotalValue.end());
}
ERROR
In file included from /usr/include/c++/7/bits/char_traits.h:39:0,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from 2_max_val_of_loot.cpp:1:
/usr/include/c++/7/bits/stl_algobase.h: In instantiation of ‘void std::iter_swap(_ForwardIterator1, _ForwardIterator2) [with _ForwardIterator1 = std::_Rb_tree_iterator<std::pair<const int, int> >; _ForwardIterator2 = std::_Rb_tree_iterator<std::pair<const int, int> >]’:
/usr/include/c++/7/bits/stl_algo.h:2926:22: required from ‘bool std::__next_permutation(_BidirectionalIterator, _BidirectionalIterator, _Compare) [with _BidirectionalIterator = std::_Rb_tree_iterator<std::pair<const int, int> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’
/usr/include/c++/7/bits/stl_algo.h:2966:2: required from ‘bool std::next_permutation(_BIter, _BIter) [with _BIter = std::_Rb_tree_iterator<std::pair<const int, int> >]’
2_max_val_of_loot.cpp:39:53: required from here
/usr/include/c++/7/bits/stl_algobase.h:148:11: error: use of deleted function ‘typename std::enable_if<(! std::__and_<std::__is_swappable<_T1>, std::__is_swappable<_T2> >::value)>::type std::swap(std::pair<_T1, _T2>&, std::pair<_T1, _T2>&) [with _T1 = const int; _T2 = int; typename std::enable_if<(! std::__and_<std::__is_swappable<_T1>, std::__is_swappable<_T2> >::value)>::type = void]’
swap(*__a, *__b);
~~~~^~~~~~~~~~~~
In file included from /usr/include/c++/7/bits/stl_algobase.h:64:0,
from /usr/include/c++/7/bits/char_traits.h:39,
from /usr/include/c++/7/ios:40,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from 2_max_val_of_loot.cpp:1:
/usr/include/c++/7/bits/stl_pair.h:503:5: note: declared here
swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete;
MY OBSERVATION
next_permutation() is creating error, but why i don't understand why.
next_permutation() requires bidirectional iterator and multimap iterator is a bidirectional iterator.
I doubt as multimap are sorted always, that's why the error is shown ??
Please Help.
Thanking You.
You cannot use std::map or std::multimap (or unordered versions) as std::next_permutation requires:
-BidirIt must meet the requirements of ValueSwappable and LegacyBidirectionalIterator.
but std::multimap values are not swappable as key in the map is not mutable:
value_type std::pair<const Key, T>
(emphasis is mine)
Less formally order of elements in map is determined and cannot me changed. You have to use different container like std::vector to perform this operation.

"no matching function for call" when trying to use the erase function on a vector

I'm trying to use the erase function to delete any ints from my vector with a value of 0.
void eliminateZeroes(std::vector<int> &answers){
auto i = answers.cbegin();
while(i != answers.cend()){
if(*i == 0){
i = answers.erase(i);
}else{
i++;
}
}
I expect the function to remove any items from the vector which are valued 0.
Error message:
/home/ec2-user/environment/DP378-Havel_Hakimi_-_Easy/main.cpp: In function ‘void eliminateZeroes(std::vector<int>&)’:
/home/ec2-user/environment/DP378-Havel_Hakimi_-_Easy/main.cpp:32:36: error: no matching function for call to ‘std::vector<int>::erase(__gnu_cxx::__normal_iterator<const int*, std::vector<int> >&)’
i = answers.erase(i);
^
/home/ec2-user/environment/DP378-Havel_Hakimi_-_Easy/main.cpp:32:36: note: candidates are:
In file included from /usr/include/c++/4.8.5/vector:69:0,
from /home/ec2-user/environment/DP378-Havel_Hakimi_-_Easy/main.cpp:1:
/usr/include/c++/4.8.5/bits/vector.tcc:134:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = int*]
vector<_Tp, _Alloc>::
^
/usr/include/c++/4.8.5/bits/vector.tcc:134:5: note: no known conversion for argument 1 from ‘__gnu_cxx::__normal_iterator<const int*, std::vector<int> >’ to ‘std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}’
/usr/include/c++/4.8.5/bits/vector.tcc:146:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = int*]
vector<_Tp, _Alloc>::
^
/usr/include/c++/4.8.5/bits/vector.tcc:146:5: note: candidate expects 2 arguments, 1 provided
It seems that you are using an old compiler that does not completely support the C++ 11 Standard.
The problem is that the constant iterator produced by the function cbegin
auto i = answers.cbegin();
can not be converted to a non-constant iterator that is used in the old declaration of the member function erase prior the C++ 11 Standard.
In the current C++ Standard the function is declared like
iterator erase(const_iterator position);
and your code should compile.
So instead of
auto i = answers.cbegin();
you need to use
auto i = answers.begin();
But in any case it is better to define the function the following way
#include <vector>
#include <algorithm>
std::vector<int> & eliminateZeroes( std::vector<int> &answers )
{
answers.erase( std::remove( answers.begin(), answers.end(), 0 ), answers.end() );
return answers;
}
If your compiler supports general functions begin, end and so on declared in the header <iterator> then the function can be rewritten also like
#include <vector>
#include <algorithm>
#include <iterator>
std::vector<int> & eliminateZeroes( std::vector<int> &answers )
{
answers.erase( std::remove( std::begin( answers ), std::end( answers ), 0 ), std::end( answers ) );
return answers;
}

Passing const_iterator to erase doesn't compile on gcc 4.7.1 [duplicate]

The following example will not compile using g++ 4.8.2:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v {1, 2, 3};
v.erase(v.cbegin()); // Compiler complains
return 0;
}
The compiler says the following. (It isn't very readable, but it's complaining that there's not a known conversion between vector<int>::const_iterator and vector<int>::iterator.)
prog.cpp: In function ‘int main()’:
prog.cpp:8:20: error: no matching function for call to ‘std::vector<int>::erase(std::vector<int>::const_iterator)’
v.erase(v.cbegin());
^
prog.cpp:8:20: note: candidates are:
In file included from /usr/include/c++/4.8/vector:69:0,
from prog.cpp:2:
/usr/include/c++/4.8/bits/vector.tcc:134:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = int*]
vector<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/vector.tcc:134:5: note: no known conversion for argument 1 from ‘std::vector<int>::const_iterator {aka __gnu_cxx::__normal_iterator<const int*, std::vector<int> >}’ to ‘std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}’
/usr/include/c++/4.8/bits/vector.tcc:146:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = int*]
vector<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/vector.tcc:146:5: note: candidate expects 2 arguments, 1 provided
Why? The C++11 standard plainly states, in §23.3.6.5, that the vector::erase function takes a const_iterator. (Paraphrases are here and here.)
What's a good workaround, assuming that I must use a const_iterator?
This is a known bug in gcc: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57158
erase requires an iterator instead of a const_iterator with current gcc's.
You can get a non-const iterator via pointer arithmetic, here's a helper function to do that:
template<typename T>
typename std::vector<T>::iterator
const_iterator_cast(std::vector<T>& v, typename std::vector<T>::const_iterator iter)
{
return v.begin() + (iter - v.cbegin());
}
used like so:
std::vector<T> v(1);
auto citer = v.cbegin();
v.erase( const_iterator_cast(v, citer) );

Missing const_iterator overload of std::vector::erase() with g++ 4.8

The following example will not compile using g++ 4.8.2:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v {1, 2, 3};
v.erase(v.cbegin()); // Compiler complains
return 0;
}
The compiler says the following. (It isn't very readable, but it's complaining that there's not a known conversion between vector<int>::const_iterator and vector<int>::iterator.)
prog.cpp: In function ‘int main()’:
prog.cpp:8:20: error: no matching function for call to ‘std::vector<int>::erase(std::vector<int>::const_iterator)’
v.erase(v.cbegin());
^
prog.cpp:8:20: note: candidates are:
In file included from /usr/include/c++/4.8/vector:69:0,
from prog.cpp:2:
/usr/include/c++/4.8/bits/vector.tcc:134:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = int*]
vector<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/vector.tcc:134:5: note: no known conversion for argument 1 from ‘std::vector<int>::const_iterator {aka __gnu_cxx::__normal_iterator<const int*, std::vector<int> >}’ to ‘std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}’
/usr/include/c++/4.8/bits/vector.tcc:146:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::iterator) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = int*]
vector<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/vector.tcc:146:5: note: candidate expects 2 arguments, 1 provided
Why? The C++11 standard plainly states, in §23.3.6.5, that the vector::erase function takes a const_iterator. (Paraphrases are here and here.)
What's a good workaround, assuming that I must use a const_iterator?
This is a known bug in gcc: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57158
erase requires an iterator instead of a const_iterator with current gcc's.
You can get a non-const iterator via pointer arithmetic, here's a helper function to do that:
template<typename T>
typename std::vector<T>::iterator
const_iterator_cast(std::vector<T>& v, typename std::vector<T>::const_iterator iter)
{
return v.begin() + (iter - v.cbegin());
}
used like so:
std::vector<T> v(1);
auto citer = v.cbegin();
v.erase( const_iterator_cast(v, citer) );