auto fails. What is the type here?

Mar 19, 2014 at 3:07am
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 Mar 19, 2014 at 3:08am
Mar 19, 2014 at 3:10am
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 Mar 19, 2014 at 3:13am
Mar 19, 2014 at 3:14am
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 Mar 19, 2014 at 3:21am
Mar 19, 2014 at 3:21am
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 Mar 19, 2014 at 3:27am
Mar 19, 2014 at 3:25am
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 Mar 19, 2014 at 3:48am
Mar 19, 2014 at 3:54am
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 Mar 19, 2014 at 3:58am
Mar 19, 2014 at 3:55am
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 Mar 19, 2014 at 4:07am
Mar 19, 2014 at 3:57am
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
Mar 19, 2014 at 3:58am
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 Mar 19, 2014 at 4:05am
Mar 19, 2014 at 4:00am
@JLBorges: Is this always the case with pointers to member functions? That we have to explicitly account for the this parameter?
Mar 19, 2014 at 4:03am
Yes.
A non-static member function with one explicit argument has an arity of two.
Topic archived. No new replies allowed.