Passing something as this argument discards qualifiers - c++

Using the below code, i get the following compile error:
In static member function ‘static std::string ctedata::Record::getDispatcher<std::basic_string<char> >::impl(const ctedata::Record&, const string&)’:
/home/jason/CrownTheEmpire/lib/ctedata/data.h:111:38: error: passing ‘const std::map<std::basic_string<char>, std::basic_string<char> >’ as ‘this’ argument discards qualifiers [-fpermissive]
return rec.fieldValues_[field];
^
In file included from /usr/include/c++/5.1.0/map:61:0,
from /usr/include/cppconn/connection.h:30,
from /usr/include/cppconn/driver.h:30,
from /home/jason/CrownTheEmpire/lib/ctedata/data.h:6,
from /home/jason/CrownTheEmpire/lib/ctedata/data.cc:3:
/usr/include/c++/5.1.0/bits/stl_map.h:471:7: note: in call to ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::basic_string<char>; _Tp = std::basic_string<char>; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::basic_string<char> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::basic_string<char>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::basic_string<char>]’
operator[](const key_type& __k)
^
class Record
{
public:
Record() {
isNew_ = true;
}
Record(sql::ResultSet *resultSet) : resultSet_(resultSet) {
isNew_ = false;
}
void loadData();
virtual void init() = 0;
bool isNew() { return isNew_; }
void setValue(const std::string& field, const std::string& value);
template<typename T>
T getValue(const std::string& field) const {
return Record::getDispatcher<T>::impl(*this, field);
}
protected:
sql::ResultSet* resultSet_;
bool isNew_;
std::map<std::string, DataTypes> fieldDataTypes_;
std::map<std::string, std::string> fieldValues_;
private:
template<typename T>
struct getDispatcher;
};
template<>
struct Record::getDispatcher<std::string> {
static std::string impl(Record const& rec, std::string& const field) {
return rec.fieldValues_[field];
}
};
template<>
struct Record::getDispatcher<int> {
static int impl(Record const& rec, const std::string& field) {
return 0;
}
};
I think i'm doing things correctly, but still getting this error that i can't figure out. Can anyone see where i've gone wrong? Thanks.

There are no operator[] of std::map which is const, you have to use at or find:
template<>
struct Record::getDispatcher<std::string> {
static std::string impl(Record const& rec, std::string& const field) {
return rec.fieldValues_.at(field); // throw if field is not in map.
}
};
or
template<>
struct Record::getDispatcher<std::string> {
static std::string impl(Record const& rec, std::string& const field) {
auto it = rec.fieldValues_.find(field);
if (it == rec.fieldValues_.end()) {
// not found.
// Manage the case, return default value or throw.
} else {
return it->second;
}
}
};

Related

unordered_map from own type by overloading operator() fails

What's wrong with the operator() inside Entity (hasher) ?
Copy-pasting it to a separate struct works :
#include <bitset>
#include <unordered_map>
using namespace std;
struct Entity {
string name;
size_t operator()(const Entity& k) const noexcept
{ return std::hash<string>{}(k.name); }
bool operator== (const Entity& e) const noexcept
{ return e.name == name; }
};
struct KeyHasher {
size_t operator()(const Entity& k) const noexcept
{ return std::hash<string>{}(k.name); }
};
int main(){
// unordered_map<const Entity, bitset<24>, KeyHasher> m1; // OK
unordered_map<const Entity, bitset<24>> m2; // unordered_map() ill-formed ?
return 0;
}
Error :
<source>: In function 'int main()':
<source>:25:43: error: use of deleted function 'std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map()
[with _Key = const Entity; _Tp = std::bitset<24>; _Hash = std::hash<const Entity>; _Pred = std::equal_to<const Entity>; _Alloc = std::allocator<std::pair<const Entity, std::bitset<24> > >]'
25 | unordered_map<const Entity, bitset<24>> m2;
| ^~
In file included from /opt/compiler-explorer/gcc-cxx-modules-trunk-20220427/include/c++/11.0.0/unordered_map:47,
from <source>:3:
/opt/compiler-explorer/gcc-cxx-modules-trunk-20220427/include/c++/11.0.0/bits/unordered_map.h:141:7: note: 'std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map() [with _Key = const Entity; _Tp = std::bitset<24>; _Hash = std::hash<const Entity>; _Pred = std::equal_to<const Entity>; _Alloc = std::allocator<std::pair<const Entity, std::bitset<24> > >]'
is implicitly deleted because the default definition would be ill-formed:
141 | unordered_map() = default;
run
If you don't specify a hash function for your map it defaults to std::hash<Key> with your key type.
So you will need to define this specialization of std::hash
template<>
struct std::hash<const Entity>
{
std::size_t operator()(const Entity const& k) const noexcept
{
return std::hash<string>{}(k.name);
}
}

How to solve ambiguity in operator overloading embedded inside a struct?

In the following code, the g++ compiler surprisingly cannot decide which operator to use when they are embedded in a struct to serve as a comparator argument in a set:
#include <string>
#include <set>
struct KeyWord {
std::string str;
int qt;
KeyWord(const std::string aKw = "", const int aQt = 0) : str(aKw), qt(aQt) {}
};
struct CompareKeywords {
bool operator() (const std::string& left, const std::string& right) const {
if (left.size() > right.size()) return true;
else if (left.size() < right.size()) return false;
else return (left < right);
}
bool operator() (const KeyWord& left, const KeyWord& right) {
if (left.str.size() > right.str.size()) return true;
else if (left.str.size() < right.str.size()) return false;
else return (left.str < right.str);
}
};
int main() {
std::set<std::string, CompareKeywords> a;
std::set<KeyWord, CompareKeywords> b;
std::string s("_s_");
KeyWord k("_k_", 1);
a.insert(s);
b.insert(k);
}
Here is the compiler output:
g++ oa.cpp
/usr/include/c++/4.9/bits/stl_tree.h: In instantiation of ‘std::pair<std::_Rb_tree_node_base*, std::_Rb_tree_node_base*> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_unique_pos(const key_type&) [with _Key = std::basic_string<char>; _Val = std::basic_string<char>; _KeyOfValue = std::_Identity<std::basic_string<char> >; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::key_type = std::basic_string<char>]’:
/usr/include/c++/4.9/bits/stl_tree.h:1498:47: required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = std::basic_string<char>; _Val = std::basic_string<char>; _KeyOfValue = std::_Identity<std::basic_string<char> >; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >]’
/usr/include/c++/4.9/bits/stl_set.h:502:29: required from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const value_type&) [with _Key = std::basic_string<char>; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<std::basic_string<char> >; std::set<_Key, _Compare, _Alloc>::value_type = std::basic_string<char>]’
oa.cpp:28:13: required from here
oa.cpp:11:8: note: candidate 1: bool CompareKeywords::operator()(const string&, const string&) const
bool operator() (const std::string& left, const std::string& right) const {
^
oa.cpp:16:8: note: candidate 2: bool CompareKeywords::operator()(const KeyWord&, const KeyWord&)
bool operator() (const KeyWord& left, const KeyWord& right) {
^
oa.cpp:11:8: note: candidate 1: bool CompareKeywords::operator()(const string&, const string&) const
bool operator() (const std::string& left, const std::string& right) const {
^
oa.cpp:16:8: note: candidate 2: bool CompareKeywords::operator()(const KeyWord&, const KeyWord&)
bool operator() (const KeyWord& left, const KeyWord& right) {
^
/usr/include/c++/4.9/bits/stl_tree.h: In instantiation of ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, const _Val&) [with _Key = std::basic_string<char>; _Val = std::basic_string<char>; _KeyOfValue = std::_Identity<std::basic_string<char> >; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::basic_string<char> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr = std::_Rb_tree_node_base*]’:
/usr/include/c++/4.9/bits/stl_tree.h:1502:38: required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = std::basic_string<char>; _Val = std::basic_string<char>; _KeyOfValue = std::_Identity<std::basic_string<char> >; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >]’
/usr/include/c++/4.9/bits/stl_set.h:502:29: required from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const value_type&) [with _Key = std::basic_string<char>; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<std::basic_string<char> >; std::set<_Key, _Compare, _Alloc>::value_type = std::basic_string<char>]’
oa.cpp:28:13: required from here
oa.cpp:11:8: note: candidate 1: bool CompareKeywords::operator()(const string&, const string&) const
bool operator() (const std::string& left, const std::string& right) const {
^
oa.cpp:16:8: note: candidate 2: bool CompareKeywords::operator()(const KeyWord&, const KeyWord&)
bool operator() (const KeyWord& left, const KeyWord& right) {
^
The last lines show the ambiguity where the compiler shows two candidates.
Why this ambiguity exist? How should I supress it?
It looks like some builds of gcc have this peculiar feature of printing these messages out of the blue. For example all builds on coliru do this.
These messages are not errors because the object file is produced, and they are not warnings because -Werror doesn't turn them into errors. They look rather like a compiler bug. Obviously one cannot suppress these non-warnings with compiler flags.
Same exact versions of gcc on my machine don't print any messages with this code. They do print regular (tagged with the coloured "warning", non-suppressible, but turnable-to-error) warnings with similar code.
On coliru, making the second operator() const suppresses the messages.
Two separate struct with only one operator in each of them dedicated to a type solves the problem:
#include <string>
#include <set>
struct KeyWord {
std::string str;
int qt;
KeyWord(const std::string aKw = "", const int aQt = 0) : str(aKw), qt(aQt) {}
};
struct CompareStrings {
bool operator() (const std::string& left, const std::string& right) const {
if (left.size() > right.size()) return true;
else if (left.size() < right.size()) return false;
else return (left < right);
}
};
struct CompareKeywords {
bool operator() (const KeyWord& left, const KeyWord& right) {
if (left.str.size() > right.str.size()) return true;
else if (left.str.size() < right.str.size()) return false;
else return (left.str < right.str);
}
};
int main() {
std::set<std::string, CompareStrings> a;
std::set<KeyWord, CompareKeywords> b;
std::string s("_s_");
KeyWord k("_k_", 1);
a.insert(s);
b.insert(k);
}
There was an error in the initial code:
bool operator() (const std::string& left, const std::string& right) const {
bool operator() (const KeyWord& left, const KeyWord& right) {
Suppressing the const at the end of the first declaration, or adding one to the second one solves the problem. But still, I don't understand why the compiler was confused.
So, either:
bool operator() (const std::string& left, const std::string& right) {
bool operator() (const KeyWord& left, const KeyWord& right) {
or:
bool operator() (const std::string& left, const std::string& right) const {
bool operator() (const KeyWord& left, const KeyWord& right) const {
works.
Note: Wheither a const function or not is discussed here.
Since I want overloading, both functions are expected to have the same behaviour, so const to both or none. If I would have liked different behaviours with one with const and the other without (in the case I would have had some struct members I would have wanted to modify), the second solution below with separate struct for each operator definition would be the solution.

Error when iterating through a map<std::string, std::string>

I have tried several ways of iterating over my "entries" map, but all of them produce the same lengthy error message.
dylan#Aspire-one:~$ g++ -std=c++11 dictionary.cpp
In file included from /usr/include/c++/4.8/map:60:0,
from dictionary.h:6,
from dictionary.cpp:1:
/usr/include/c++/4.8/bits/stl_tree.h: In instantiation of ‘void
std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare,
_Alloc>::_M_insert_unique(_II, _II) [with _InputIterator =
std::basic_string<char>; _Key = std::basic_string<char>; _Val =
std::pair<const std::basic_string<char>, std::basic_string<char> >;
_KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>,
std::basic_string<char> > >; _Compare = std::less<std::basic_string<char>
>; _Alloc = std::allocator<std::pair<const std::basic_string<char>,
std::basic_string<char> > >]’:
/usr/include/c++/4.8/bits/stl_map.h:226:11: required from
‘std::map<_Key, _Tp, _Compare, _Alloc>::map(_InputIterator,
_InputIterator) [with _InputIterator = std::basic_string<char>; _Key =
std::basic_string<char>; _Tp = std::basic_string<char>; _Compare =
std::less<std::basic_string<char> >; _Alloc =
std::allocator<std::pair<const std::basic_string<char>,
std::basic_string<char> > >]’
dictionary.h:11:66: required from here
/usr/include/c++/4.8/bits/stl_tree.h:1721:28: error: no match for
‘operator++’ (operand type is ‘std::basic_string<char>’)
for (; __first != __last; ++__first)
^
/usr/include/c++/4.8/bits/stl_tree.h:1722:29: error: no match for
‘operator*’ (operand type is ‘std::basic_string<char>’)
_M_insert_unique_(end(), *__first);
^
dylan#Aspire-one:~$
Here is my most recent code.
dictionary.cpp
#include "dictionary.h"
//I have included <string> <map> <iterator> "from dictionary.h"
bool dictionary::search_term(const std::string& term){
std::map<std::string, std::string>::iterator it;
for (it = entries.begin(); it != entries.end(); ++it){
if(it->first != term);
else return true;
}return false;
};
So the error is in "dictionary.h"?
dictionary.h
#ifndef DICTIONARY_H
#define DICTIONARY_H
#include <iterator>
#include <string>
#include <map>
class dictionary{
public:
dictionary(const std::string& title, const std::string& definition = "")
: entries(std::map<std::string, std::string>(title, definition)){;};
bool write_entry(const std::string& term, const std::string& definition = "");
bool define_term(const std::string& term, const std::string& definition);
bool erase_entry(const std::string& term);
bool search_term(const std::string& term);
private:
std::map<std::string, std::string> entries;
};
#endif//DICTIONARY_H
In the constructor, use brace initialization for the map:
dictionary(const std::string& title, const std::string& definition = "")
: entries{ {title, definition} } {;};
(EDIT: forgot one level of braces)
or set the element in the constructor body
dictionary(const std::string& title, const std::string& definition = "")
{
entries[title] = definition;
}
The problem is in the definition of the constructor of class dictionary. std::mapdoesn't have a constructor that takes a single key-value pair, so the easiest way to initialize with one pair is to use the universal initializer syntax. You'll need two pairs of braces, one for the list of key-value pairs, and one for the single pair you want to define:
dictionary(const std::string& title, const std::string& definition = "")
: entries(std::map<std::string, std::string>(title, definition)){;};
dictionary(const std::string& title, const std::string& definition = "")
: entries{ {title, definition} } {}

I can`t solve a passing constant error with my actual knowledge [duplicate]

This question already has an answer here:
std::map access operator deprecated? no operator [] matches these operands
(1 answer)
Closed 8 years ago.
I made a specialization for a bidirectional map when the key type and value type are the same.
Also I made 2 definitions for the operator[] ,one to return constant and one to return non constant. But this did not solve my problem.I get an error that i`m passing constant as *this...
Here it is the specialization:
template<class A>
class BidirectionalMap<A,A>
{
public:
void insert(A a,A b)
{
m1.insert(std::pair<A,A> (a,b));
m1.insert(std::pair<A,A> (b,a));
}
BidirectionalMap& operator =(BidirectionalMap &a)
{
m1=a.m1;
return *this;
}
const A& at(const A& a) const
{
return m1.at(a);
}
int size() const
{
return m1.size();
}
int count(const A& a) const
{
return m1.count(a);
}
A& operator[](const A& a)
{
return m1[a];
}
const A& operator[](const A& a) const
{
return m1[a];////here pinpoints me that error: passing 'const std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >' as 'this' argument of 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = int; _Tp = int; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, int> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]' discards qualifiers [-fpermissive]
}
private:
std::map<A,A> m1;
};
And the error shows in this context:
BidirectionalMap<int, int> f;
f.insert(3, 18);
f.insert(8, 2);
f.insert(7, 5);
f.insert(9, 1);
const BidirectionalMap<int, int> cf = f;
if( f.at(5) == 7 &&
f.count(12) == 0 &&
f.at(8) == 2)
{
yourMark = cf[18] + cf[9];//here is the error
}
Any idea?
operator[] is typically not const in std::map
See http://www.cplusplus.com/reference/map/map/operator%5B%5D/
The reason is that operator[] allows to insert if the element is not present.

Find in a map using the base class with a boost::shared_ptr

I'm looking for a way to find an element inside a map using the base class (the code bellow is just a basic example):
#include <map>
#include <boost/shared_ptr.hpp>
class Base {
public:
Base(int v) : id(v) {};
int id;
};
class Derived : public Base {
public:
Derived(int v) : Base(v) {};
};
int main()
{
std::map<boost::shared_ptr<Derived>, double> m;
m.insert(std::make_pair(boost::shared_ptr<Derived>(new Derived(1)), 10));
m.insert(std::make_pair(boost::shared_ptr<Derived>(new Derived(2)), 20));
auto b1 = boost::shared_ptr<Base>(new Base(1));
m.find(b1);
return 0;
}
Basically, I want to compare the id attribute. The errors returned by the compiler are the following:
main.cpp: In function 'int main()':
main.cpp:35:14: error: no matching function for call to 'std::map<boost::shared_ptr<Derived>, double>::find(boost::shared_ptr<Base>&)'
m.find(b1);
^
main.cpp:35:14: note: candidates are:
In file included from /usr/include/c++/4.8/map:61:0,
from main.cpp:1:
/usr/include/c++/4.8/bits/stl_map.h:820:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::find(const key_type&) [with _Key = boost::shared_ptr<Derived> _Tp = double; _Compare = std::less<boost::shared_ptr<Derived> > _Alloc = std::allocator<std::pair<const boost::shared_ptr<Derived>, double> > std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const boost::shared_ptr<Derived>, double> > std::map<_Key, _Tp, _Compare, _Alloc>::key_type = boost::shared_ptr<Derived>]
find(const key_type& __x)
^
/usr/include/c++/4.8/bits/stl_map.h:820:7: note: no known conversion for argument 1 from 'boost::shared_ptr<Base>' to 'const key_type& {aka const boost::shared_ptr<Derived>&}'
/usr/include/c++/4.8/bits/stl_map.h:835:7: note: std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator std::map<_Key, _Tp, _Compare, _Alloc>::find(const key_type&) const [with _Key = boost::shared_ptr<Derived> _Tp = double; _Compare = std::less<boost::shared_ptr<Derived> > _Alloc = std::allocator<std::pair<const boost::shared_ptr<Derived>, double> > std::map<_Key, _Tp, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const boost::shared_ptr<Derived>, double> > std::map<_Key, _Tp, _Compare, _Alloc>::key_type = boost::shared_ptr<Derived>]
find(const key_type& __x) const
^
/usr/include/c++/4.8/bits/stl_map.h:835:7: note: no known conversion for argument 1 from 'boost::shared_ptr<Base>' to 'const key_type& {aka const boost::shared_ptr<Derived>&}'
If you want to use your map for lookup by id, you need to pass in an appropriate comparison function so that the map sorts its keys by id instead of the default operator < (which, I believe, compares ownership block addresses with boost::shared_ptr arguments).
So change the map like this:
struct Less_id
{
bool operator() (const boost::shared_ptr<Derived> &lhs, const boost::shared_ptr<Derived> &rhs) const
{
return lhs->id < rhs->id;
}
};
typedef std::map<boost::shared_ptr<Derived>, double, Less_id> Map;
Map m;
This will sort the map accordingly, but still not allow lookup by Base pointer. To do that, you can write your own function above std::lower_bound:
Map::const_iterator find_base(const Map &map, const boost::shared_ptr<Base> &base)
{
auto it = std::lower_bound(
map.begin(), map.end(), base,
[](const Map::value_type &lhs, const boost::shared_ptr<Base> &rhs)
{ return lhs.first->id < rhs->id; }
);
if (it != map.end() && it->first->id == base->id)
return it;
else
return map.end();
}
std::lower_bound() is used to keep the logarithmic complexity std::map::find() offers.
Live example
Use an
std::map<boost::shared_ptr<Derived>, double, std::less<boost::shared_ptr<Base>>>
Edit: I am ahead of the times - this only works for C++14.
There are two issues to overcome. The first is that you want to search for a Base in a collection of Deriveds. The second is that you want to compare by value rather than by address. The other answers are neglecting this second point. Try std::find_if:
auto b1 = boost::shared_ptr<Base>(new Base(1));
auto itFound = std::find_if(m.begin(), m.end()
[=](const std::pair<boost::shared_ptr<Derived>, double>& pair)
{
// omitting null checks for this example
return pair.first->id == b1->id;
});
And if the requirement is really just to find a key with the given id, you could make it simpler:
int queryKey = 1;
auto itFound = std::find_if(m.begin(), m.end()
[=](const std::pair<boost::shared_ptr<Derived>, double>& pair)
{
return pair.first->id == queryKey;
});
Now, as noted in the comments, this will give you linear rather than map's usual logarithmic lookup time. If the map is small it won't matter, but if this is an issue, you could use std::lower_bound instead of find_if. Note that this would also require adding a custom comparer so you could ensure the map's sort order was based on id. For example:
struct Compare
{
bool operator()(const boost::shared_ptr<Derived>& l,
const boost::shared_ptr<Derived>& r) const
{
// omitting null checks for this example
return l->id < r->id;
}
};
std::map<boost::shared_ptr<Derived>, double, Compare> m;
This is because boost::shared_ptr's operator < is not what you want, you need a delegation to the Derived class's operator <.
use std::map<_Key, _Tp, _Compare>
for example:
std::map<boost::shared_ptr<Derived>, double, compare_func()> m;
As you are looking for an object Base which can only be in the map if it is of type Derived you can simply do this:
boost::shared_ptr<Derived> d1 = boost::dynamic_pointer_cast<Derived>(b1);
if(d1) {
m.find(d1);
} else {
// not in the map
}
As you use std::shared_ptr<Derived> as a key, another possibility would be to actually use pointers to the base class instead:
Use
std::map<boost::shared_ptr<Base>, double> m;
instead of
std::map<boost::shared_ptr<Derived>, double> m;
and everything works as expected.
Btw, you are missing a virtual destructor in Base!