3

I'm trying to map string to function pointer, so that I can call the function with iter->second(arg) instead of if-else. I have written a simple one without class, and it works as expected. But when I modify it as below, it shows compile errors.

 #include <functional>
 #include <iostream>
 #include <unordered_map>
 #include <string>

 using std::string;

 class A{
     private:
     int a(int num, string s) { return s.size() + num; }
     int b(int num, string s) { return num - s.size(); }

     public:
     void ido(string str){
         typedef std::function<int(int, string)> process_func;
         std::unordered_map<string, process_func> m;
         m.insert(std::make_pair<string, process_func>("a", &A::a));
         // using std::placeholders::_1;
         // m.insert(std::make_pair<string, process_func>("a", std::bind(&A::a, this, _1)));
         // m["a"] = std::bind(&A::a, this, _1);
         // m.insert({{"a", &A::a}, {"b", &A::b}});

         auto x = m.find(str);
         if(x == m.end()) {
             std::cout << "Not supported!" << std::endl;
         }
         std::cout << x->second(10, "hello") << std::endl;
     }
 };
 int main(int argc, char* argv[]) {
     A a;
     a.ido(string(argv[1]));
     return 0;
 }

The errors are:

function.cc: In member function ‘void A::ido(std::string)’:
function.cc:17:65: error: no matching function for call to ‘make_pair(const char [2], int (A::*)(int, std::string))’
         m.insert(std::make_pair<string, process_func>("a", &A::a));
                                                                 ^
function.cc:17:65: note: candidate is:
In file included from /usr/include/c++/4.8.2/utility:70:0,
                 from /usr/include/c++/4.8.2/tuple:38,
                 from /usr/include/c++/4.8.2/functional:55,
                 from function.cc:1:
/usr/include/c++/4.8.2/bits/stl_pair.h:276:5: note: template<class _T1, class _T2> constexpr std::pair<typename std::__decay_and_strip<_Tp>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&)
     make_pair(_T1&& __x, _T2&& __y)
     ^
/usr/include/c++/4.8.2/bits/stl_pair.h:276:5: note:   template argument deduction/substitution failed:
function.cc:17:65: note:   cannot convert ‘&A::a’ (type ‘int (A::*)(int, std::string) {aka int (A::*)(int, std::basic_string<char>)}’) to type ‘std::function<int(int, std::basic_string<char>)>&&’
         m.insert(std::make_pair<string, process_func>("a", &A::a));

What does the error mean? How to fix it?

Roy Huang
  • 579
  • 3
  • 23
  • 1
    Looks like a dup of this: https://stackoverflow.com/questions/7582546/using-generic-stdfunction-objects-with-member-functions-in-one-class – Eljay Nov 26 '19 at 03:54

1 Answers1

2

While your functions 'a' and 'b' do not depend on 'this' (they do not access anything inside class A), the compiler is not smart enough to deduce this. So the error means that you are trying to convert 'pointer to method' to 'pointer to function', which is incorrect conversion. 'Pointer to method' requires and object to be called on. You need to declare methods 'a' and 'b' as 'static' to indicate that they are actually standalone functions, not methods of the class.

  • Btw, could you explain what is the difference between `pointer to method` and `pointer to function`? – Roy Huang Nov 27 '19 at 03:23
  • 2
    All arguments of a function are explicit. So all you need to call a function by pointer is the pointer itself and arguments declared in the signature of the function. Method of a class have a hidden argument that turns into 'this' inside of a method. i.e. in order to call a method you need an object of compatible type in addition to arguments. //function void foo(int x); auto fooptr = &foo; fooptr(1); class A{ public: void foo(int x); }; auto afooptr = &A::foo; A obj; (obj.*afooptr)(1); – Konstantin Stupnik Nov 27 '19 at 07:15
  • 1
    static method is from 'pointer to' point of view is a function. It doesn't require an object and have no 'this' available. – Konstantin Stupnik Nov 27 '19 at 07:26