find struct in vector - c++

I want to find a struct in a vector, but I'm having some troubles. I read several posts about this, but these all search for one element of the struct: I want to be able to compare multiple elements of the struct while searching. My struct and vector are defined as:
struct subscription {
int tournamentid;
int sessionid;
int matchid;
bool operator==(const subscription& m) const {
return ((m.matchid == matchid)&&(m.sessionid==sessionid)&&(m.tournamentid==tournamentid));
}
};
vector<subscription> subscriptions;
Then I want to search for a struct in the vector subscriptions, but since the combination of sessionid and matchid is unique, I need to search for both. Searching for only one will result in multiple results.
subscription match;
match.tournamentid = 54253876;
match.sessionid = 56066789;
match.matchid = 1108;
subscriptions.push_back(match);
it = find(subscriptions.begin(), subscriptions.end(), match);
The find function give the following error during compiling:
main.cpp:245:68: error: no match for ‘operator=’ in ‘it = std::find [with _IIter = __gnu_cxx::__normal_iterator >, _Tp = echo_client_handler::subscription](((echo_client_handler*)this)->echo_client_handler::subscriptions.std::vector<_Tp, _Alloc>::begin with _Tp = echo_client_handler::subscription, _Alloc = std::allocator, std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator >, typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer = echo_client_handler::subscription*, ((echo_client_handler*)this)->echo_client_handler::subscriptions.std::vector<_Tp, _Alloc>::end with _Tp = echo_client_handler::subscription, _Alloc = std::allocator, std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator >, typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer = echo_client_handler::subscription*, (*(const echo_client_handler::subscription*)(& match)))’
And a WHOLE lot more :) So the operator is not defined correctly, but how should that be done? Can anyone help me? How to search for multiple elements instead of only one element of a struct?

May be you did not specified type for it?
std::vector<subscription>::iterator it =
find(subscriptions.begin(), subscriptions.end(), match);

Related

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.

priority queue in stl

I followed the article to code a hanffman coding method using stl's priority_queue, however I think there are some bugs in the final code or it's not updated. The main problem is the declaration of the priority_queue, I believe it should take three parameters like: priority_queue< node, vector, greater > q, instead of priority_queue, greater > q.
However, even with this changes, the gcc compiler still give the errors like:
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h: In member function ‘bool std::greater<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = node]’:
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:279: instantiated from ‘void std::__adjust_heap(_RandomAccessIterator, _Distance, _Distance, _Tp, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<node*, std::vector<node, std::allocator<node> > >, _Distance = long int, _Tp = node, _Compare = std::greater<node>]’
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_heap.h:404: instantiated from ‘void std::make_heap(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<node*, std::vector<node, std::allocator<node> > >, _Compare = std::greater<node>]’
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_queue.h:367: instantiated from ‘std::priority_queue<_Tp, _Sequence, _Compare>::priority_queue(const _Compare&, const _Sequence&) [with _Tp = node, _Sequence = std::vector<node, std::allocator<node> >, _Compare = std::greater<node>]’ hanffman.cpp:119: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:218: error: no match for ‘operator>’ in ‘__x > __y’
which I don't understand. The full code is available here
You need to define an operator>() for your class because you are using std::greater<> as the comparison in the priority_queue. The only operator I saw in the code was operator<().
You are missing the definition of the > operator for node (you only define the < operator).

Is it possible to use STL copy function with map

I wonder if there is any trick to use copy with maps to copy the contents of map into an array. Because STL maps are by the combination of a key value and a mapped value an element of a map forms a key value pair. That prevents us to use standard algorithms like std::copy. For example following code gives error:
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
int
main()
{
std::map <int, double> test(4);
test[0] = 11;
test[2] = 1.23;
test[3] = 23.29;
test[1] = 12.12;
double *test_arr = (double *) malloc(4 * sizeof(double));
std::copy(test.begin(), test.end(), test_arr);
std::cout << test_arr[3] << std::endl;
return 0;
}
Error:
stl_copy_tests.cpp: In function ‘int main()’:
stl_copy_tests.cpp:9:32: error: no matching function for call to ‘std::map<int, double>::map(int)’
/usr/include/c++/4.5/bits/stl_map.h:170:7: note: candidates are: std::map<_Key, _Tp, _Compare, _Alloc>::map(const std::map<_Key, _Tp, _Compare, _Alloc>&) [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >, std::map<_Key, _Tp, _Compare, _Alloc> = std::map<int, double>]
/usr/include/c++/4.5/bits/stl_map.h:159:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::map(const _Compare&, const allocator_type&) [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >, allocator_type = std::allocator<std::pair<const int, double> >]
/usr/include/c++/4.5/bits/stl_map.h:150:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::map() [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >]
In file included from /usr/include/c++/4.5/bits/char_traits.h:41:0,
from /usr/include/c++/4.5/ios:41,
from /usr/include/c++/4.5/ostream:40,
from /usr/include/c++/4.5/iostream:40,
from stl_copy_tests.cpp:1:
/usr/include/c++/4.5/bits/stl_algobase.h: In static member function ‘static _OI std::__copy_move<<anonymous>, <anonymous>, <template-parameter-1-3> >::__copy_m(_II, _II, _OI) [with _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*, bool <anonymous> = false, bool <anonymous> = false, <template-parameter-1-3> = std::bidirectional_iterator_tag]’:
/usr/include/c++/4.5/bits/stl_algobase.h:404:70: instantiated from ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false, _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’
/usr/include/c++/4.5/bits/stl_algobase.h:442:39: instantiated from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false, _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’
/usr/include/c++/4.5/bits/stl_algobase.h:474:18: instantiated from ‘_OI std::copy(_II, _II, _OI) [with _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’
stl_copy_tests.cpp:15:47: instantiated from here
/usr/include/c++/4.5/bits/stl_algobase.h:319:6: error: cannot convert ‘std::pair<const int, double>’ to ‘double’ in assignment
Is there any easy trick/hack to overcome this problem.
Disclaimer: Not interested in solutions that iterates over map in a for loop and adds elements to the array.
You could use std::transform instead:
template <typename T, typename U>
const U &extract_second(const std::pair<T,U> &p)
{
return p.second;
}
std::transform(test.begin(), test.end(), test_arr, extract_second<int,double>);
And as #Andre points out in a comment below, if you want a slightly more verbose overhead, you can avoid having to explicitly state the template arguments via a functor:
struct extract_second
{
template <typename T, typename U>
const U operator() (const std::pair<T,U> &p) const
{
return p.second;
}
};
std::transform(test.begin(), test.end(), test_arr, extract_second());
I'm sure there's a less-verbose solution using Boost binders, but I can't remember the syntax off the top of my head.
Ewww, malloc? Anyway, if you want to copy a map, you have to remember the keys too.
int main()
{
std::map <int, double> test(4);
test[0] = 11;
test[2] = 1.23;
test[3] = 23.29;
test[1] = 12.12;
std::vector<std::pair<int, double>> test_arr(test.size());
std::copy(test.begin(), test.end(), test_arr.begin());
std::cout << test_arr[3] << std::endl;
return 0;
}
If you consider std::map an STL container, then it is a container of
std::pair<key_type, mapped_type>. (This is what its value_type is
defined to be, and it is designed so that it can be used as a
container.) If you want simply one part of it, the correct function is
std::transform, with a transformation function which maps the
value_type to either the key_type or the mapped_type. (If you make
much use of std::pair—or std::map, whose value_type is an
std::pair, you should probably have functional objects for this in
your tool kit:
struct ExtractFirst
{
template<typename Pair>
typename boost::remove_const<typename Pair::first_type>::type
operator()( Pair const& from ) const
{
return from.first;
}
};
, and the same thing for ExtractSecond.
Your target would be an arraystd::vector[please!] of std::pair<int,double> objects unless, yes, you unroll it yourself.
(You could create your own InputIterator as a proxy, or play with std::transform and a std::back_inserter, but that's just being silly. You'll make your code far more verbose than just looping through the map.)
The simplest way is to use std::transform in combination with boost::bind:
typedef std::map<int, double> map_t;
map_t mm;
// add elements to mm
// ...
// copy
typedef std::vector<double> vec_t;
vec_t vv;
vv.reserve( mm.size() );
std::transform( mm.begin(), mm.end(), std::back_inserter(vv),
boost::bind( &map_t::value_type::second, _1 ) );
If you could use C++0x (without boost):
std::transform( mm.begin(), mm.end(), back_inserter(vv),
[](map_t::value_type val) -> double { return val.second; } );
// or
std::for_each( mm.begin(), mm.end(),
[&vv](map_t::value_type val) { vv.push_back( val.second ); } );

How to pass normal param as well as template param in a template function in C++?

I have a template function (as follows) in a namespace called myNamespace:
template <typename setX>
void getRandomItems(NaturalNumber size, setX &random, setX &items)
{
assert(size <= items.size());
//set of randomly selected indices for items
set<NaturalNumber> index;
NaturalNumber r, i;
while(index.size() < size)
{
r = unifRand(0,items.size()-1);
index.insert(r);
}
typename setX::iterator it, sit = items.begin();
for(i = 0, it = index.begin(); it != index.end(); it ++)
{
//find the r-th elt in index
r = *it;
for(; i < r; i ++)
sit++;
random.insert(*sit);
}
}
However whenever I call this function I get these errors:
generic.h: In function ‘void myNamespace::getRandomItems(NaturalNumber, setX&, setX&) [with setX = std::set<std::basic_string<char> >, NaturalNumber = long unsigned int]’:
synthetic-graph.C:87:55: instantiated from here
generic.h:74:32: error: no match for ‘operator=’ in ‘it = index.std::set::begin [with _Key = long unsigned int, _Compare = std::less<long unsigned int>, _Alloc = std::allocator<long unsigned int>, std::set<_Key, _Compare, _Alloc>::iterator = std::_Rb_tree_const_iterator<long unsigned int>]()’
/usr/include/c++/4.5/bits/stl_tree.h:224:5: note: candidate is: std::_Rb_tree_const_iterator<std::basic_string<char> >& std::_Rb_tree_const_iterator<std::basic_string<char> >::operator=(const std::_Rb_tree_const_iterator<std::basic_string<char> >&)
synthetic-graph.C:87:55: instantiated from here
generic.h:74:32: error: no match for ‘operator!=’ in ‘it != index.std::set<_Key, _Compare, _Alloc>::end [with _Key = long unsigned int, _Compare = std::less<long unsigned int>, _Alloc = std::allocator<long unsigned int>, std::set<_Key, _Compare, _Alloc>::iterator = std::_Rb_tree_const_iterator<long unsigned int>]()’
/usr/include/c++/4.5/bits/stl_tree.h:291:7: note: candidate is: bool std::_Rb_tree_const_iterator<_Tp>::operator!=(const std::_Rb_tree_const_iterator<_Tp>::_Self&) const [with _Tp = std::basic_string<char>, std::_Rb_tree_const_iterator<_Tp>::_Self = std::_Rb_tree_const_iterator<std::basic_string<char> >]
generic.h:77:4: error: cannot convert ‘const std::basic_string<char>’ to ‘NaturalNumber’ in assignment
I have tried all combinations but no luck, please help me!!!
setX is not a set of NaturalNumbers so the iterators aren't compatible when you say it = index.begin(). You could possibly make it an iterator of set<NaturalNumber> instead, I can't quite make out what you really want to do here.
Also I noticed that in your inner loop you don't do any checks to make sure sit doesn't run off the end of its set.
You're trying to assign incompatible iterators.
Perhaps you meant
set<NaturalNumber>::iterator it;
typename setX::iterator sit = items.begin();
instead of
typename setX::iterator it, sit = items.begin();

Problem compiling stl map insert

I'm having trouble compiling the following code:
typedef std::map<mUUID, block_ptr_t> BlockMap;
BlockMap _store;
std::pair< BlockMap::iterator, bool > it;
it = _store.insert(hint, std::make_pair(entry.block_uid, block));
The error is:
error: no match for ‘operator=’ in ‘it = BlockStore::_store.std::map<_Key, _Tp, _Compare, _Alloc>::insert [with _Key = mUUID, _Tp = Block*, _Compare = std::less<mUUID>, _Alloc = std::allocator<std::pair<const mUUID, Block*> >](lb, ((const std::pair<const mUUID, Block*>&)(& std::pair<const mUUID, Block*>(((const std::pair<mUUID, Block*>&)((const std::pair<mUUID, Block*>*)(& std::make_pair(_T1, _T2) [with _T1 = mUUID, _T2 = Block*](block))))))))’
/usr/include/c++/4.4/bits/stl_pair.h:68: note: candidates are: std::pair<std::_Rb_tree_iterator<std::pair<const mUUID, Block*> >, bool>& std::pair<std::_Rb_tree_iterator<std::pair<const mUUID, Block*> >, bool>::operator=(const std::pair<std::_Rb_tree_iterator<std::pair<const mUUID, Block*> >, bool>&)
It seems to be related to the assignment because if I don't assign it to "it" it compiles without error.
The version of insert that takes a hint returns only an iterator, not a pair.
First of all, your example is incomplete - _store is defined nowhere.
Second, it seems you are trying to assign an iterator to a std::pair - why do you need a pair, anyway?
The following should work, provided that _store is of type BlockMap:
BlockMap::iterator it;
it = _store.insert(std::make_pair(entry.block_uid, block));