0

I have a map of pointer to member declared as :

std::map<char, T (Operand::*)(const T &, const T &)> op_map;

I fill my map with pointer to member directly in the constructor of my class with :

op_map['+'] = &Operand::op_add;

For example, op_add source code is :

  T op_add(const T & a, const T & b) {
    return a + b;
  }

And I want to call my pointer to member from a const function. Here is the source code :

  IOperand *res_int32(char op, const IOperand & rhs) const {
    IOperand *res = const_cast<IOperand *>(&rhs);
    Operand<int> *tmp = dynamic_cast<Operand<int>*>(res);
    T res_calc = (this->*op_map[op])(_value, (T)tmp->getValue());
  }

But it makes me always an error :

Operand.hpp:70:64: error: passing ‘const std::map<char, double (Operand<double>::*)(const double&, const double&), std::less<char>, std::allocator<std::pair<const char, double (Operand<double>::*)(const double&, const double&)> > >’ as ‘this’ argument of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = char, _Tp = double (Operand<double>::*)(const double&, const double&), _Compare = std::less<char>, _Alloc = std::allocator<std::pair<const char, double (Operand<double>::*)(const double&, const double&)> >, std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = double (Operand<double>::*)(const double&, const double&), std::map<_Key, _Tp, _Compare, _Alloc>::key_type = char]’ discards qualifiers [-fpermissive]
Operand.hpp:70:64: error: invalid conversion from ‘const Operand<double>* const’ to ‘Operand<double>*’ [-fpermissive]

Have you got any solution ?

Thank you.

Jeffrey Muller
  • 850
  • 1
  • 15
  • 28

3 Answers3

2

operator[] can't be applied to a const map, since it inserts a new element if the key is not found.

In C++11, there is an at function which throws an exception if the key is not found:

T res_calc = (this->*op_map.at(op))(_value, (T)tmp->getValue());
                           ^^^^^^^

In C++03, you'll need to use find:

map_type::const_iterator found = op_map.find(op);
if (found != op_map.end()) {
    T res_calc = (this->*(found->second))(_value, (T)tmp->getValue());
} else {
    // handle error
}

You'll also need to change the type of the member functions in the map to

T (Operand::*)(const T &, const T &) const
                                     ^^^^^

in order to call them on this from a const member function.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

Just make op_add a const member function.

 T op_add(const T & a, const T & b) const // <<<
 {
   return a + b;
 }

And instead of the std::map::operator[] use std::map::find http://www.cplusplus.com/reference/stl/map/find/

EDIT:

You also need to change the map type to std::map<char, T (Operand::*)(const T &, const T &) const> op_map, as correctly pointed by R. Martinho Fernandes.

Gigi
  • 4,953
  • 24
  • 25
0

If you know what you are doing, you can try to compile with the c++ flag -fpermissive as G++ said.

Adrien BARRAL
  • 3,474
  • 1
  • 25
  • 37
  • 2
    If you know what you're doing, then you'll know that's a very bad idea. – Mike Seymour Feb 09 '12 at 11:27
  • 2
    No, please. `-fpermissive` enables way too many things you don't ever want enabled. It's *too permissive*. And you can always solve the problem with a *real solution* without the need for `-fpermissive`. – R. Martinho Fernandes Feb 09 '12 at 11:27