How to insert a reference to a multimap? - c++11

I have a class Foo that contains a multimap with an unsigned long and a reference to a Bar class.
I'm getting the error "no matching function to call multimap, etc".
What is wrong on my insert into the multimap?
[header file]
class Foo
{
public:
Foo();
~Foo();
void set(const unsigned long var1, const Bar& var2);
private:
struct map_sort
{
bool operator()(const unsigned long& e1, const unsigned long& e2) const
{
return (e2 < e1);
}
};
std::multimap<unsigned long,Bar&, map_sort> m_map;
};
[source file]
void Foo::set(const unsigned long var1, const Bar& var2)
{
m_map.insert(var1,rtime); //<-- ERROR!!!!!!!!
}

You multimap member is declared to take unsigned long and Bar&
std::multimap<unsigned long,Bar&, map_sort> m_map;
while, in source file
void Foo::set(const unsigned long var1, const Bar& var2)
{
m_map.insert(var1,rtime); //var1 is const here! (rtime is not declared but I assume you meant var2 - which is const, too)
}
you are trying to insert const unsigned long and const Bar& which differ from the ones declared above (they are constant). Note that the const unsigned long isn't really an issue because it is copied by value so, in fact, the multimap keeps its own version of the variable and the "main" one can't be modified whatsoever.
Additionally, check out the documentation of multimap's insert method http://www.cplusplus.com/reference/map/multimap/insert/. You should use std::pair to insert key-value pair:)
Solution 1: Change your method to take non-const arguments:
void set(unsigned long var1, Bar& var2);
Solution 2: Change your map to contain const values:
std::multimap<const unsigned long, const Bar&, map_sort> m_map
Working example:
class Foo
{
public:
Foo();
~Foo();
void set(const unsigned long var1, const Bar& var2);
private:
struct map_sort
{
bool operator()(const unsigned long& e1, const unsigned long& e2) const
{
return (e2 < e1);
}
};
std::multimap<const unsigned long, const Bar&, map_sort> m_map;
};
void Foo::set(const unsigned long var1, const Bar& var2)
{
m_map.insert(pair<const unsigned long, const Bar&>(var1, var2));
}

Related

C++ multiset error C2676: binary '-': 'const _BidIt' does not define this operator or a conversion to a type acceptable to the predefined operator

I have the following C++ classes:
class MyClass {
private:
int _id;
unsigned long long _timestamp;
public:
MyClass(int id, unsigned long long ts) : _id(id), _timestamp(ts) {}
bool operator<(const MyClass& other) const { return _timestamp < other._timestamp; }
int GetID() {return _id;}
};
class MyClass1 {
private:
map<int, multiset<MyClass>> _list;
public:
vector<int> GetMyClasses(int id, int count) {
vector<int> result;
transform(_list[id].rbegin(), _list[id].rbegin() + count, back_inserter(result), [](const MyClass& c) {return c.GetID();});
return result;
}
};
This is the build error:
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\include\xutility(1915,41): error C2676: binary '-': 'const _BidIt' does not define this operator or a conversion to a type acceptable to the predefined operator
I am using VS2019 Version 16.7.7. Any insight and advice is appreciated.
You cannot increment an iterator of multiset by simple +.
Use std::advance to do it:
auto it = _list[id].rbegin();
auto it2 = it;
std::advance(it2,count);
transform(it, it2,
back_inserter(result), [](const MyClass& c) {return c.GetID();});
also GetID must be const method.
Demo

Why am I getting a bad_function_call exception when using std::function as a comparison function object in std::map

I am getting a std::__1::bad_function_call: std::exception when I execute the code below.
I have tried initializing std::function in the constructor and initializing it directly when defined as a class variable. In both cases I get the aforementioned exception.
Note that if I define a function object (a class with a bool operator () function defined), the code works properly. How can I capture a lambda into std::function so that no exception is thrown? Also, what is causing the exception in the code below?
#include <map>
using namespace std;
class foo {
public:
foo() {cmp = [](const int &a, const int &b){return a > b;};}
//function<bool(const int &a, const int &b)> cmp = [](const int &a, const int &b){return a > b;};
function<bool(const int &a, const int &b)> cmp;
map<int, int, decltype(cmp)> rbtree;
};
int main() {
foo* obj = new foo();
obj->rbtree[5] = 5;
obj->rbtree[1] = 5;
obj->rbtree[5] = 5;
}
You may be looking for something like this:
class foo {
public:
using Cmp = function<bool(int a, int b)>;
map<int, int, Cmp> rbtree { [](int a, int b){return a > b;} };
};
Demo

Boost recursive variant along with template c++

I am trying to understand boost recursive variant and template. For the below code, I get compilation error of
cannot convert argument 1 from 'std::vector<std::string,std::allocator<_Ty>>' to 'const Boost::variant<boost::detail::variant::recursive_flag<T0>,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19> &'
Error seems to be originating from GetVarValue() function
As per my undertanding I can have a class with _default : which can be vector of int, string, bool, double, vector of int/string/bool/double right?
typedef boost::make_recursive_variant<
int,
std::string,
bool,
double,
std::vector<boost::recursive_variant_> >::type TokenValueType;
template<class T>
class VectorToken : public Token
{
private:
string _name;
vector<T> _default;
public:
VectorToken(string name, vector<T> defaultVal)
: _name(name)
{
_default = defaultVal;
}
virtual TokenValueType GetVarValue()
{
return _default; <-- _default (vector<string>) doesn't like TokenValueType ?
}
};
main()
{
vector<string> tempvec = {"ABC", "LMN", "PQR"};
VectorToken<string> t4 = VectorToken<string>::VectorToken("VECTORSTR", tempvec);
}
The error goes away when I write main like this:
main()
{
vector<TokenValueType> tempvec = { string("ABC"), string("LMN"), string("PQR") };
VectorToken<TokenValueType> t4 = VectorToken<TokenValueType>::VectorToken("VECTORSTR", tempvec);
}
I will simplify that type:
typedef boost::make_recursive_variant<
int,
std::string,
std::vector<boost::recursive_variant_> >::type TokenValueType;
This should be enough to explain it.
TokenValueType is not a variant over (vector of int, vector of string, vector of vector of TokenValueType).
It is a vector over (int or string or TokenValueType).
Here is a MCVE with your syntax errors corrected and one line changed:
return std::vector<TokenValueType>(_default.begin(), _default.end());

Return type mismatch for operator implementation in unordered_map wrapper

I am implementing a simple wrapper on top of std::unordered_map with user-defined hash functions and simple iterator/const_iterator. Most of the parts are working but I am stuck with * and -> operator implementations. The mapping from returns types of unordered_map operators to my wrapper operators are hitting compilation error due to type-mismatch errors.
Basically, both "return internalItr" and "return &(*internalItr)" are hitting type-mismatch. However, for testing sake (commented code), I used a const member variable in the const_iterator class, but then the assignment "return_type = *internalItr" works, which is basically the same type-conversion. But keeping a const member variable in const_iterator is not a solution for me as it will hit other issues due to const-ness in "it=h.begin()". I cannot change any public api signatures due to legacy library code and my options are limited. I am sorry for posting this long code chunk but couldn't find a better way to illustrate my scenario of a std::unordered_map with 3 template parameters. However, I have omitted the non-interesting/working template implementation codes for the sake of brevity, but included all the api's to provide the background.
Your comments are appreciated!
template< class Key >
class HashFunction
{
public:
HashFunction(){};
HashFunction( const Key & inKey );
inline operator unsigned() const
{
return hashCode;
}
size_t operator()(const Key &inKey) const;
private:
unsigned hashCode;
};
template< class Key, class Val, class Hash = HashFunction< Key > >
class unordered_map_wrapper
{
private:
typedef typename unordered_map<Key,Val,Hash>::const_iterator int_const_iterator;
typedef typename unordered_map<Key,Val,Hash>::iterator int_iterator;
public:
typedef std::pair< Key, Val > key_value;
class iterator
{
friend class unordered_map_wrapper;
private:
iterator( int_iterator & inIterator );
public:
iterator();
private:
int_iterator internalItr;
};
class const_iterator
{
friend class unordered_map_wrapper;
private:
const_iterator( const int_const_iterator & inIterator );
public:
const_iterator();
const key_value & operator*() const;
const key_value * operator->() const;
const_iterator & operator++();
bool operator!=( const const_iterator & inIterator ) const;
private:
int_const_iterator internalItr;
//const key_value return_type;
};
const_iterator begin() const
{
return const_iterator( mTable->begin() );
}
const_iterator end() const
{
return const_iterator( mTable->end() );
}
unordered_map_wrapper();
std::pair< iterator, bool > insert(const key_value & inPair);
private:
unordered_map<Key, Val, Hash> * mTable;
};
template< class Key, class Val, class Hash >
unordered_map_wrapper< Key, Val, Hash >::const_iterator::const_iterator()
{
}
template< class Key, class Val, class Hash >
unordered_map_wrapper< Key, Val, Hash >::const_iterator::const_iterator( const int_const_iterator & inIterator ) :
internalItr( inIterator )
{
}
template< class Key, class Val, class Hash >
unordered_map_wrapper< Key, Val, Hash >::unordered_map_wrapper()
{
mTable=new unordered_map<Key, Val, Hash>(10);
}
template< class Key, class Val, class Hash >
const typename unordered_map_wrapper< Key, Val, Hash >::key_value & unordered_map_wrapper< Key, Val, Hash >::const_iterator::operator*() const
{
return *internalItr;
}
template< class Key, class Val, class Hash >
const typename unordered_map_wrapper< Key, Val, Hash >::key_value * unordered_map_wrapper< Key, Val, Hash >::const_iterator::operator->() const
{
//return internalItr;
return &(*internalItr);
//return_type = *internalItr;
//return &return_type;
}
int main() {
unordered_map_wrapper<string, unsigned> h;
unordered_map_wrapper<string, unsigned>::const_iterator it;
h.insert(std::make_pair<string, unsigned>(string("One"), 1));
std::cout << "MAP VALUES: " << endl;
for ( it = h.begin() ; it != h.end(); ++it )
std::cout << " " << it->first << ":" << it->second << endl;
return 0;
}
Compilation error:
error: cannot convert 'const std::pair<const std::basic_string<char>, unsigned int>*' to 'const key_value* {aka const std::pair<std::basic_string<char>, unsigned int>*}' in return
return &(*internalItr); ^
or
error: cannot convert 'const int_const_iterator {aka const std::__detail::_Node_const_iterator<std::pair<const std::basic_string<char>, unsigned int>, false, true>}' to 'const key_value* {aka const std::pair<std::basic_string<char>, unsigned int>*}' in return
return internalItr;
^
I could get around the above above issue by:
typedef std::pair< const Key, Val > key_value;
But now hitting some other issue. Whenever I add another nonconst-overloaded begin() fn it fails. Why is this not able to pick the correct begin() based on the const-ness which works with a typical STL container?
iterator begin()
{
return iterator( mTable->begin());
}
The error message is:
prog.cpp:159:22: error: no match for ‘operator=’ (operand types are ‘unordered_map_wrapper<std::__cxx11::basic_string<char>, unsigned int>::const_iterator’ and ‘unordered_map_wrapper<std::__cxx11::basic_string<char>, unsigned int>::iterator’)
for ( it = h.begin() ; it != h.end(); ++it )
prog.cpp:75:13: error: invalid initialization of non-const reference of type
‘unordered_map_wrapper<std::__cxx11::basic_string<char>, unsigned
int>::int_iterator& {aka std::__detail::_Node_iterator<std::pair<const
std::__cxx11::basic_string<char>, unsigned int>, false, true>&}’ from an
rvalue of type ‘std::unordered_map<std::__cxx11::basic_string<char>,
unsigned int, HashFunction<std::__cxx11::basic_string<char> >,
std::equal_to<std::__cxx11::basic_string<char> >,
std::allocator<std::pair<const std::__cxx11::basic_string<char>, unsigned
int> > >::iterator {aka std::__detail::_Node_iterator<std::pair<const
std::__cxx11::basic_string<char>, unsigned int>, false, true>}’
return iterator( mTable->begin());
^~~~~~~~~~~~~~~~~~~~~~~~~~

boost::iterator_facade operator->() fails to compile

Consider the following code:
#include <boost/iterator/iterator_facade.hpp>
#include <map>
// Class implements an stl compliant iterator to access the "sections" stored within a configuration.
template < typename _Iterator, typename _Reference >
class Section
: public boost::iterator_facade<
Section< _Iterator, _Reference >,
_Iterator,
boost::random_access_traversal_tag,
_Reference
>
{
private:
// Define the type of the base class:
typedef boost::iterator_facade<
Section< _Iterator, _Reference >,
_Iterator,
boost::random_access_traversal_tag,
_Reference
> base_type;
public:
// The following type definitions are common public typedefs:
typedef Section< _Iterator, _Reference > this_type;
typedef typename base_type::difference_type difference_type;
typedef typename base_type::reference reference;
typedef _Iterator iterator_type;
public:
explicit Section( const iterator_type it )
: m_it( it )
{ }
// Copy constructor required to construct a const_iterator from an iterator:
template < typename _U >
Section( const Section< _U, _Reference > it )
: m_it( it.m_it )
{ }
private:
// The following classes are friend of this class to ensure access onto the private member:
friend class boost::iterator_core_access;
template < typename _Iterator, typename _Reference > friend class Section;
void increment( ){ ++m_it; } // Advance by one position.
void decrement( ){ --m_it; } // Retreat by one position.
void advance( const difference_type& n ){ m_it += n }; // Advance by n positions.
bool equal( const this_type& rhs ) const{ return m_it == rhs.m_it; } // Compare for equality with rhs.
reference dereference( ) const { return m_it->second; } // Access the value referred to.
difference_type distance_to( const this_type& rhs ) const{ return rhs.m_it - m_it; } // Measure the distance to rhs.
private:
// Current "section" iterator:
iterator_type m_it;
};
struct Data
{
void f( ) const
{ }
};
typedef std::map< int, Data > map_type;
typedef Section< const map_type::const_iterator, const Data& > iterator_type;
map_type g_map;
iterator_type begin( )
{
return iterator_type( g_map.begin( ) );
}
void main( )
{
iterator_type i = begin( );
// i->f( ); // <--- error C2039: 'f' : is not a member of 'std::_Tree_const_iterator<_Mytree>'
( *i ).f( );
}
So the iterator facade shall return a reference to Data type. This works well when dereference operator is called but compile fails when operator->() is called. So I am a bit confused because operator->() tries to return a std::map::iterator. Any ideas ?
The iterator returns an iterator on dereference. To get the f part, you need to dereference twice.
It looks a lot like you misunderstood the meaning of the template arguments to iterator_facade. The second argument is not supposed to be any iterator type (this is what causes all your trouble). Instead you should use it to name your value_type.¹
From the way you specified the dereference operation (and Ref) and wanted to use it in main (i->f()) it looks like you just wanted to iterate the map's values. So, I'd rewrite the whole thing using more descriptive names as well, and here it is, working:
Live On Coliru
#include <boost/iterator/iterator_facade.hpp>
#include <map>
// Class implements an stl compliant iterator to access the "sections" stored within a configuration.
template <typename Map, typename Value = typename Map::mapped_type>
class MapValueIterator : public boost::iterator_facade<MapValueIterator<Map>, Value, boost::random_access_traversal_tag, Value const&> {
private:
// Define the type of the base class:
typedef Value const& Ref;
typedef boost::iterator_facade<MapValueIterator<Map>, Value, boost::random_access_traversal_tag, Ref> base_type;
public:
// The following type definitions are common public typedefs:
typedef MapValueIterator<Map> this_type;
typedef typename base_type::difference_type difference_type;
typedef typename base_type::reference reference;
typedef typename Map::const_iterator iterator_type;
public:
explicit MapValueIterator(const iterator_type it) : m_it(it) {}
// Copy constructor required to construct a const_iterator from an iterator:
template <typename U, typename V> MapValueIterator(const MapValueIterator<U,V> it) : m_it(it.m_it) {}
private:
// The following classes are friend of this class to ensure access onto the private member:
friend class boost::iterator_core_access;
template <typename U, typename V> friend class MapValueIterator;
void increment() { std::advance(m_it); } // Advance by one position.
void decrement() { std::advance(m_it, -1); } // Retreat by one position.
void advance(const difference_type &n) { std::advance(m_it, n); } // Advance by n positions.
bool equal(const this_type &rhs) const { return m_it == rhs.m_it; } // Compare for equality with rhs.
reference dereference() const { return m_it->second; } // Access the value referred to.
difference_type distance_to(const this_type &rhs) const { return rhs.m_it - m_it; } // Measure the distance to rhs.
private:
// Current iterator:
iterator_type m_it;
};
#include <iostream>
struct Data {
void f() const {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
typedef std::map<int, Data> map_type;
template <typename Map>
MapValueIterator<Map> map_value_iterator(Map const& m) {
return MapValueIterator<Map>(m.begin());
}
int main() {
map_type g_map;
auto i = map_value_iterator(g_map);
i->f();
}
Which prints the output
void Data::f() const
as you'd expect.
Note that there are numerous places where I implemented the member functions using standard library facilities. Note as well, the iterator "mimics" random access, but it won't have the expected performance characteristics (increment is O(n)).
Final note: I'd recommend against having the implicit conversion constructor. I think you can do without it.
¹ The reference-type should typically be the same (but ref-qualified) except in rare cases where you actually "proxy" the values. This is an advanced topic and rarely should be used.

Resources