auto fails. What is the type here?

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <map>
#include <functional>

struct A {
	void func1 (int x) {};
	void func2 (int x) {};
	void mapping() {
		std::map<int, std::function<void(int)>> myMap = { {1, func1}, {2, func2} };
		// do whatever
	}
};

int main() {}


std::map<int, std::function<void(int)>> is apparently not the correct type, and 'auto' cannot deduce the type either. So what is the type to make this compile???
Last edited on
std::map's value_type is std::pair. What you are passing are initializer lists.
1
2
3
4
5
using funct_type = std::function<void(int)>;
std::map<int, funct_type> myMap = {
    std::make_pair(1, funct_type(func1)),
    std::make_pair(2, funct_type(funct2))
);
Last edited on
No that doesn't work either (with typos fixed). Initializer lists can initialize a map, but I'll use std::pair anyway.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <map>
#include <functional>
#include <utility>

struct A {
	void func1 (int x) {};
	void func2 (int x) {};
	void mapping() {
		using funct_type = std::function<void(int)>;

		std::map<int, funct_type> myMap = {
    		std::make_pair(1, funct_type(func1)),
    		std::make_pair(1, funct_type(func2))
		}; 
		// do whatever
	}
};

int main() {}

does not compile. Additional note: I cannot turn func1, func2 static in my program. When func1 and func2 are global, it compiles. So the complication is due to them being member functions of A.
Last edited on
Works fine for me. Sample code I used to test this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <functional>
#include <map>
#include <utility>

int main()
{
    auto f1 = [](int i){std::cout << i;};
    auto f2 = [](int i){std::cout << '[' << i << ']';};

    using funct_type = std::function<void(int)>;

    std::map<int, funct_type> myMap = {
        std::make_pair(1, funct_type(f1)),
        std::make_pair(2, funct_type(f2))
    };

    for(auto it(myMap.begin()); it != myMap.end(); ++it){
        it->second(37);
        std::cout << '\n';
    }

    return 0;
}


And the output:

37
[37]


Edit:
Saw your edit. I never knew we could use aggregate initialization in an initializer_list. I've always used std::make_pair. :V

Have you tried writing out the fully scoped name of the function? I've never attempted using member functions like that.
Last edited on
My note above: When func1 and func2 are global, it compiles. So the complication is due to them being member functions of A.

Try compiling my code above. It does not work.

->Have you tried writing out the fully scoped name of the function? I've never attempted using member functions like that.

I tried that too, and then I was forced to turn the functions static to make it compile. But the functions cannot be static in my program. There is a special syntax for class member function pointers. Perhaps I'll try that.

typdef void (A::*func_pointer) (int);
Last edited on
I've never worked with pointers to member functions before, so... Any gurus would be more than welcome to jump in.

After a bit of fidgeting around, I found that I had to use void (A::*)(int) as the type, and I tried passing the address-of the member function (I've tried a couple other ways but this was the closest), but I ran into this error:

This is an error caused from "&(A::func1)"
ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function
 to form a pointer to member function.  Say '&A::func1' [-fpermissive]|

The compiler then says the type of the instantiation if I don't use the parentheses.
 invalid use of incomplete type 'using funct_type = 
class std::function<void (A::*)(int)> {aka class std::function<void (A::*)(int)>}'|



Warning: Really messy code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <map>
#include <functional>
#include <utility>
#include <iostream>
#include <typeinfo>

struct A {
	void func1 (int x);
	void marbles (int x);
	void mapping();
};

int main() {
    A temp;
    temp.mapping();
    return 0;
}

void A::func1(int i){std::cout << i;}
void A::marbles(int i){std::cout << '[' << i << ']';}

#include <cxxabi.h>

void A::mapping(){
    using funct_type = std::function<void (A::*)(int)>;
    std::map<int, funct_type> myMap{
        {1, funct_type(&(A::func1))},
        {2, funct_type(&A::marbles)}
    };
/* Below is code I used to find the name of type for instantiation
    auto ptr = &A::func1;
    int s(-4);
    std::cout << abi::__cxa_demangle(typeid(ptr).name(), nullptr, nullptr, &s) << '\n';
*/
}
Last edited on
Also does not compile is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <map>
#include <functional>

struct A {
	void func1 (int x) {};
	void func2 (int x) {};

	typedef void (A::*func_pointer) (int); 

	void mapping() {
		std::map<int, func_pointer> myMap = {
    		{1, func1},
    		{1, func2}
		}; 
		// do whatever
	}
};

int main() {}

And 'auto' failing also raises some eyebrows. This is also my first time defining a map this way, but I do need it for my program.
Edit: Saw your post above just now. I appreciate your time and effort. Will look into this, but I'm surprised that so much work is involved just to make it compile (if it still does comple, that is).

Rats! It your solution code does not compile with my GCC 4.8.1. It only compiles if I take out the
1
2
3
4
    std::map<int, funct_type> myMap{
        {1, funct_type(&(A::func1))},
        {2, funct_type(&A::marbles)}
    };
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <map>
#include <functional>

struct A {
    
    void func1 (int) {};
    void func2 (int) {};
    
    void mapping() {
        // std::map<int, std::function<void(int)>> myMap = { {1, func1}, {2, func2} };
        
        using std::placeholders::_1 ;
        std::map< int, std::function<void(int)> > myMap = { { 1, std::bind( &A::func1, this, _1 ) }, 
                                                            { 2, std::bind( &A::func2, this, _1 ) } };
        
        std::map<int, std::function< void( A*, int )> > myMap2 = { { 1, &A::func1 }, { 2, &A::func2 } };
	// do whatever
    }
};

int main() {}

http://coliru.stacked-crooked.com/a/0c68fac3bab9b949
If you're wrapping a non-static member function of A that takes int into an std::function, you have to take two parameters: a reference or pointer to A and the int:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <map>
#include <functional>

struct A {
    void func1 (int x) {};
    void func2 (int x) {};
    void mapping() {
        std::map<int, std::function<void(A&, int)>> myMap1 = {
                 {1, &A::func1}, {2, &A::func2} };
        std::map<int, std::function<void(A*, int)>> myMap2 = {
                 {1, &A::func1}, {2, &A::func2} };

        myMap1[1](*this, 7);
        myMap2[1](this, 7);
    }
};

int main() {}


PS: you could have also stored the pmfs themselves, as Daleth did
1
2
3
4
5
    void mapping() {
        std::map<int, void(A::*)(int)> myMap = {
                 {1, &A::func1}, {2, &A::func2} };
        (this->*myMap[1])(7);
    }
Last edited on
@JLBorges: Is this always the case with pointers to member functions? That we have to explicitly account for the this parameter?
Yes.
A non-static member function with one explicit argument has an arity of two.
Topic archived. No new replies allowed.