How do you create a map of maps? - c++

I'm trying to do the following:
.h
map<int, map<int,int> > forwardingTable;
.cpp
int
UpdateForwardingTable(int dest, int hop, int cost)
{
if(forwardingTable.at(dest) != forwardingTable.end())
forwardingTable.at(dest) = make_pair(hop, cost);
else
forwardingTable.insert(dest, make_pair(hop, cost));
}
But I get a million compiler errors, similar to:
In file included from /usr/include/c++/4.8/map:60:0,
from globals.h:25,
from rtngnode.h:2,
from rtngnode.cpp:1:
/usr/include/c++/4.8/bits/stl_tree.h:316:5: note: template<class _Val> bool std::operator!=(const std::_Rb_tree_iterator<_Tp>&, const std::_Rb_tree_const_iterator<_Val>&)
operator!=(const _Rb_tree_iterator<_Val>& __x,
^
/usr/include/c++/4.8/bits/stl_tree.h:316:5: note: template argument deduction/substitution failed:
rtngnode.cpp:205:53: note: ‘std::map<int, std::map<int, int, std::less<int> > >::mapped_type {aka std::map<int, int, std::less<int> >}’ is not derived from ‘const std::_Rb_tree_iterator<_Tp>’
if(forwardingTable.at(dest) != forwardingTable.end())
Am I doing something wrong? Is there a better container for this type of thing?

There are tow problems:
1, make_pair returns pair, not map.
2, at(dest) may throws an out_of_range exception, refer map::at
It should be:
int
UpdateForwardingTable(int dest, int hop, int cost)
{
map<int, map<int,int> >::iterator itr = forwardingTable.find(dest);
if(itr != forwardingTable.end())
{
itr->second.insert(hop, cost);
// forwardingTable.at(dest) = make_pair(hop, cost);
}
else
{
map<int, int> obj;
obj.insert(hop, const);
forwardingTable.insert(dest, obj);
// forwardingTable.insert(dest, make_pair(hop, cost));
}
}

Related

Getting compiler error: Request for member push in pq, which is of non-class type std::priority_queue

I am getting below error:
:60:8: error: request for member 'push' in 'pq', which is of
non-class type 'std::priority_queue,
std::vector >, std::function, std::pair)> >(comparator)' 60 | pq.push(p1);
My code is as below:
Declared a comparator for priority_queue as below:
class comparator
{
bool operator ()(std::pair<int, int> &p, std::pair<int, int> &q)
{
return (p.second < q.second);
}
};
Declared priority queue as below:
std::priority_queue<std::pair<int, int>, vector<std::pair<int, int>>, std::function<bool(pair<int, int>, pair<int, int>)>> pq(comparator);
make pair as below:
auto p1 = make_pair(1, 3);
pushed it to priority_queue as:
pq.push(p1);
Can anyone please tell, what i am doing wrong here
The operator() must be public and should also be const qualified.
You don't need std::function here. Just supply the comparator as the third template parameter directly.
#include <queue>
#include <utility>
#include <vector>
struct comparator {
// must be public and should be const qualified:
bool operator()(std::pair<int, int> &p, std::pair<int, int> &q) const {
return p.second < q.second;
}
};
int main() {
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>,
comparator> // <- the proper comparator
pq;
auto p1 = std::make_pair(1, 3);
pq.push(p1);
}

How to use struct/std::pair correctly?

I am using struct in my project which has an unordered_map, I tried to put a struct or a pair of integers as key to the map, then manipulate the map, but couldn't compile, it says:
usr/include/c++/4.8/bits/hashtable_policy.h:1082:53: error: invalid use of incomplete type âstrruct std::hash<NAMESPACE::Span<int> >â
using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>;
operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
^
/usr/include/c++/4.8/bits/unordered_map.h:1388:5: note: template argument deduction/substitution failed:
In file included from /usr/include/c++/4.8/string:48:0,
-----------------------------------------------------------
/usr/include/c++/4.8/bits/hashtable_policy.h: In instantiation of âstruct std::__detail::_Hash_ccode_base<std::pair<int, int>, std::pair<const std::pair<int, int>, NAMESPACE::ConfigSet>, std::__detail::_Select1st, std::hash<std::pair<int, int> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>â:
/usr/include/c++/4.8/bits/unordered_map.h:100:18: required from âclass std::unordered_map<std::pair<int, int>, RTBKIT::ConfigSet>â
What's wrong? Here is my struct:
namespace MYNAMESPACE {
template<typename T>
//can pass in a list than a range for IntervalFilter
struct Span
{
//no arg/two args not working for the template typename T
//span(T lb, T ub);
//span();
T lowerBound;
T upperBound;
static Span
createFromJson(const Json::Value & val);
void fromJson(const Json::Value & val);
Json::Value toJson() const;
bool empty() const;
//didn't declare this template type, isIncluded is not used
template<typename U> bool isIncluded(const U & value) const;
};
} //namespace
#endif
The code use the struct:
...
private:
static constexpr unsigned PRIORITY = 0x1401; }
//std::unordered_map<Span<int>, ConfigSet> data;
std::unordered_map<std::pair<int,int>, ConfigSet> data;
void setConfig(unsigned configIndex, const AgentConfig& config) {
auto range = [] (int first, int last) {
return std::make_pair(first, last);
};
//int l = config.rangeFilter.lowerBound;
//int r = configrangeFilter.upperBound;
//data[config.rangeFilter].set(configIndex);
data[range(config.rangeFilter.lowerBound, config.rangeFilter.upperBound)].set(configIndex);
}
};
The problem is that the standard does not define a hash specialization for std::pair. The compiler is telling you (indirectly) that it doesn't know how to generate hash values for your keys.
You should define your own hash class and use it in your data declaration. Something like this:
struct MyHash
{
size_t operator()(std::pair<int, int> value) const
{
// I make no promise that this is a good hash function for your dataset.
return value.first + value.second;
}
};
std::unordered_map<std::pair<int, int>, ConfigSet, MyHash> data;

Bind const std::pair<T, U>& to value of std::pair<const T, U>

The below code snippet compiles with a very important warning.
#include <map>
#include <vector>
template <typename iterator>
const std::pair<int, float> &foo(iterator it) {
return *it;
}
int main() {
std::vector<std::pair<int, float>> vector;
std::map<int, float> map;
vector.push_back(std::make_pair(0, 0.0));
map.insert(std::make_pair(0, 0.0));
const std::pair<int, float> &r1 = foo(vector.begin());
const std::pair<int, float> &r2 = foo(map.begin());
if (r1 != r2) {
return 1;
}
return 0;
}
There is an implicit conversion from std::pair<const int, float> to std::pair<int, float> during foo(map.begin()) that creates a dangling reference.
ref2.cpp: In instantiation of ‘const std::pair<int, float>& foo(iterator) [with iterator = std::_Rb_tree_iterator<std::pair<const int, float> >]’:
ref2.cpp:16:52: required from here
ref2.cpp:7:11: warning: returning reference to temporary [-Wreturn-local-addr]
return *it;
^~
We could adjust the type of r2 to std::pair<const int, float> in this case. Nevertheless, it would be useful, in the general case, to assign the results of the two calls to foo() to type-compatible references. For example, the call to foo() might be wrapped in another function that always returns std::pair<int, float>&.
Can the reference assignment be made to operatate in a way that works around the misalignment of const modifiers?
Edit
The question is really about making std::pair<K,V> work with std::pair<const K,V>; vector<> and map<> are red-herrings. (In particular, see the discussion here about why the key in std::map<> is const.)
Better sample code might be:
#include <vector>
template <typename iterator>
const std::pair<const int, float>& bar(iterator it)
{
return *it;
}
int main()
{
const std::vector<std::pair<const int, float>> v1{ std::make_pair(0, 0.0f) };
bar(v1.begin());
const std::vector<std::pair<int, float>> v2{ std::make_pair(0, 0.0f) };
bar(v2.begin());
return 0;
}
According to your comments, what you're really trying to figure out is how to make the std::map<> iterator work like std::vector<>; the result should be a std::pair<> in both cases, not std::pair<const int, ...>.
With that, I've written this hack; I'm sure it's got problems and/or could be improved:
const auto& remove_const(const std::pair<const int, float>& p) {
return reinterpret_cast<const std::pair<int, float>&>(p); // :-(
}
template <typename iterator>
const std::pair<int, float> &foo(iterator it) {
return remove_const(*it);
}
You might change:
template <typename iterator>
const std::pair<int, float> &foo(iterator it) {
return *it;
}
to:
template <typename iterator>
decltype(auto) foo(iterator it) {
return *it;
}
this requires c++14, to stay with c++11 use:
auto foo(iterator it) -> decltype(*it) {

error in type conversion in operator overloading

I have a template class and I need to overload operator ==. I do this in the following way
template <typename T>
class Polynomial {
vector<T> coefficients;
public:
Polynomial(vector<T> c);
bool operator ==(const Polynomial& second) const {
const typename vector<T>::iterator thisBegin = this->coefficients.begin();
const typename vector<T>::iterator secondBegin = second.coefficients.begin();
for ( ; ((thisBegin != this->coefficients.end()) &&
(secondBegin != second.coefficients.end()));
++thisBegin, ++secondBegin) {
if (*thisBegin != *secondBegin)
return false;
}
while (thisBegin != this->coefficients.end()) {
if (*thisBegin != 0)
return false;
++thisBegin;
}
while (secondBegin != second.coefficients.end()) {
if (*secondBegin != 0)
return false;
++secondBegin;
}
return true;
}
};
However, when I create two objects of this class with T=int and try to apply this operator
Polynomial<int> first(firstVector);
Polynomial<int> second(secondVector);
std::cout << (first == second) << std::endl;
I got the error
problem2.cpp: In instantiation of ‘bool Polynomial<T>::operator==(const Polynomial<T>&) const [with T = int; Polynomial<T> = Polynomial<int>]’:
problem2.cpp:63:32: required from here
problem2.cpp:23:83: error: conversion from ‘std::vector<int, std::allocator<int> >::const_iterator {aka __gnu_cxx::__normal_iterator<const int*, std::vector<int, std::allocator<int> > >}’ to non-scalar type ‘std::vector<int, std::allocator<int> >::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >}’ requested
Can someone point out what's wrong with this conversion? Thanks!
You are trying to convert a const_iterator to an iterator:
const typename vector<T>::iterator thisBegin = this->coefficients.begin();
this is const in this context, so this->coefficients.begin(); returns a const_iterator. Try this:
typename vector<T>::const_iterator thisBegin = this->coefficients.begin();
Note also that thisBegin is not const, as in your example. This is because you then do this kind of thing:
++secondBegin;
which requires the const_iterator to be non-const (meaning you can modify the iterator, but not the thing it points to).
your method is const that mean that you can only call const functions on this and
you passing const reference to method, so you can only call const functions on it
So, both
this->coefficients.begin();
second.coefficients.begin()
returns const iterators.
You cannot assign them to non-const ones.
There is a solution:
vector<T>::const_iterator& thisBegin = this->coefficients.begin();
vector<T>::const_iterator& secondBegin = second.coefficients.begin();
(use references to const_iterator)
Even better:
auto& thisBegin = this->coefficients.begin();
auto& secondBegin = second.coefficients.begin();
(use references to auto, C++11 feature)
BTW, you can simply compare two vectors using std::mismatch

Errors when using map() in C++

I wrote a piece of code and used map and vector but it shows me something I can't get. I'll be thankful if someone help me in this way and correct my code or give me some hints.
The code is:
// For each node in N, calculate the reachability, i.e., the
// number of nodes in N2 which are not yet covered by at
// least one node in the MPR set, and which are reachable
// through this 1-hop neighbor
std::map<int, std::vector<const NeighborTuple *> > reachability;
std::set<int> rs;
for (NeighborSet::iterator it = N.begin(); it != N.end(); it++)
{
NeighborTuple const &nb_tuple = *it;
int r = 0;
for (TwoHopNeighborSet::iterator it2 = N2.begin (); it2 != N2.end (); it2++)
{
TwoHopNeighborTuple const &nb2hop_tuple = *it2;
if (nb_tuple.neighborMainAddr == nb2hop_tuple.neighborMainAddr)
r++;
}
rs.insert (r);
reachability[r].push_back (&nb_tuple);
}
/*******************************************************************************/
//for keepping exposition of a node
std::map<Vector, std::vector<const NeighborTuple *> > position;
std::set<Vector> pos;
for (NeighborSet::iterator it = N.begin(); it != N.end(); it++)
{
NeighborTuple nb_tuple = *it;
Vector exposition;
pos.insert (exposition);
position[exposition].push_back (&nb_tuple);
}
and the errors are for this line: position[exposition].push_back (&nb_tuple);
and the errors are:
/usr/include/c++/4.1.2/bits/stl_function.h: In member function ‘bool std::less<_
Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = ns3::Vector3D]’:
/usr/include/c++/4.1.2/bits/stl_map.h:347: instantiated from ‘_Tp& std::map<_K
ey, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = ns3::Vector3D, _Tp = std::vector<const ns3::olsr::NeighborTuple*, std::allocator<const ns3::olsr::NeighborTuple*> >, _Compare = std::less<ns3::Vector3D>, _Alloc = std::allocator<std::pair<const ns3::Vector3D, std::vector<const ns3::olsr::NeighborTuple*, std::allocator<const ns3::olsr::NeighborTuple*> > > >]’
../src/routing/olsr/olsr-routing-protocol.cc:853: instantiated from here
/usr/include/c++/4.1.2/bits/stl_function.h:227: error: no match for ‘operator<’ in ‘__x < __y’
debug/ns3/ipv6-address.h:432: note: candidates are: bool ns3::operator<(const ns3::Ipv6Address&, const ns3::Ipv6Address&)
debug/ns3/nstime.h:475: note: bool ns3::operator<(const ns3::Time&, const ns3::Time&)
debug/ns3/ipv4-address.h:305: note: bool ns3::operator<(const ns3::Ipv4Address&, const ns3::Ipv4Address&)
debug/ns3/address.h:231: note: bool ns3::operator<(const ns3::Address&, const ns3::Address&)
debug/ns3/type-id.h:376: note: bool ns3::operator<(ns3::TypeId, ns3::TypeId)
Thanks in advance.
Bahar
std::map is a sorted container of pairs. As such, keys in the map must have operator <() defined. Make sure Vector has the less-than operator defined.
For example:
class Vector {
int len, ang;
friend bool operator<(const Vector&, const Vector&);
};
bool operator<(const Vector& v1, const Vector& v2)
{
return true_if_v1_is_less_than_v2(); // you define what "less than" means
}
Of course, there other ways to do this. You may make operator< a member function. Or you may have the two member data public and the operator a non-member, non-friend function. Or you may define operator< in an anonymous namespace, to enhance information hiding. Or you may use a comparator other than operator<.
You declared the position object as followed : std::map<Vector, std::vector<const NeighborTuple *> > position;
And you are trying to push NeighborTuple * inside...
Try using const NeighborTuple *
I notice that you seem to have a pushback line that compiles and a line that does not.
The difference might be that you have a const in the first case
NeighborTuple const &nb_tuple = *it;