question about function pointer in classes

for example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class B
{
public:
    typedef void(*funcptr)(int); //typedef...

    funcptr sptr;

    void set_function_pointer(funcptr in){ sptr = in; }
};

B* Binst;

class A
{
public:
    A(){
        Binst->set_function_pointer(functionA);
    }

    void functionA(int param){}
};

//later I created an instance of A and initialized Binst... 


this code won't be compiled...gcc says "no matching function for call to 'B::set_function_pointer(<unresolved overloaded function type>)'"
then I tried to move the typedef out of class B, but nothing changed.(why..)
so what's wrong with this? thanks!
Last edited on
Invoking a non-static member function requires an object.

Wrap with the polymorphic call wrapper std::function<> and bind the object with the generic binder std::bind(), perhaps?

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
#include <iostream>
#include <functional>

class B
{
    public:
        typedef std::function< void(int) > func ; //typedef...

        func fn ;

        void set_function( func in ) { fn = in; }

        void call_it( int v ) { if(fn) fn(v) ; }
};

class A
{
    public:
        A( B& b )
        {
            b.set_function( std::bind( &A::functionA, this, std::placeholders::_1 ) );
        }

        void functionA(int param) const { std::cout << "A::funcA(" << param << ")\n" ; }
};

int main()
{
    B b ;
    A a(b) ;
    b.call_it(99) ; // A::funcA(99)

    b.set_function( []( long a ) { std::cout << "main::closure(" << a << ")\n" ; } ) ;
    b.call_it(726) ; // main::closure(726)
}

http://coliru.stacked-crooked.com/a/e82713de558ca481
wow...thanks very much! BTW, is std::function slow? I remember reading somewhere that it is a lot more slow than function pointer..
> is std::function slow? I remember reading somewhere that it is a lot more slow than function pointer..

The initialisation of / assignment to a std::function<> is very expensive when compared to the near zero cost of initialising a pointer to function.

There obviously is a quality of implementation consideration; in general, the overhead of forwarding the call through a std::function<> is quite negligible. And a call through a wrapped closure is typically very fast.

Here are the results of a somewhat crude, off-the-cuff test:

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
37
38
39
40
41
42
43
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <iterator>
#include <ctime>

double fun( double a, double b, double c ) { return a*a*a - b*b + c ; }

constexpr std::size_t N  = 50'000'000 ;
int a[N], b[N], c[N], result[N] ;

int main()
{

    std::iota( std::begin(a), std::end(a), 1 ) ;
    std::iota( std::begin(b), std::end(b), N+1 ) ;
    std::iota( std::begin(c), std::end(c), N*2 + 1 ) ;

    {
        const auto start = std::clock() ;
        const auto pfn = &fun ;
        for( std::size_t i = 0 ; i < N ; ++i ) result[i] = pfn( a[i], b[i], c[i] ) ;
        const auto end = std::clock() ;
        std::cout << "    raw pointer to function: " << (end-start) * 1000.0 / CLOCKS_PER_SEC << " milliseconds\n" ;
    }

    {
        const auto start = std::clock() ;
        const std::function< double(double,double,double) > fn = fun ;
        for( std::size_t i = 0 ; i < N ; ++i ) result[i] = fn( a[i], b[i], c[i] ) ;
        const auto end = std::clock() ;
        std::cout << "wrapped pointer to function: " << (end-start) * 1000.0 / CLOCKS_PER_SEC << " milliseconds\n" ;
    }

    {
        const auto start = std::clock() ;
        const std::function< double(double,double,double) > fn = []( double a, double b, double c ) { return a*a*a - b*b + c ; };
        for( std::size_t i = 0 ; i < N ; ++i ) result[i] = fn( a[i], b[i], c[i] ) ;
        const auto end = std::clock() ;
        std::cout << "            wrapped closure: " << (end-start) * 1000.0 / CLOCKS_PER_SEC << " milliseconds\n" ;
    }
}

echo '----- clang++ with libc++ ---------' && clang++ -std=c++14 -stdlib=libc++ -O3 -Wall -Wextra -pedantic-errors main.cpp -lsupc++ && ./a.out
echo '----- g++ with libstdc++ ---------' && g++ -std=c++14 -O3 -Wall -Wextra -pedantic-errors main.cpp && ./a.out

----- clang++ with libc++ ---------
    raw pointer to function: 510 milliseconds
wrapped pointer to function: 470 milliseconds
            wrapped closure: 390 milliseconds
----- g++ with libstdc++ ---------
    raw pointer to function: 460 milliseconds
wrapped pointer to function: 390 milliseconds
            wrapped closure: 360 milliseconds 

http://coliru.stacked-crooked.com/a/8f9eb1f2e6c4979c
I see now, thanks! it is even faster... ^_^
> it is even faster...

Not always.
...
----- g++ with libstdc++ ---------
    raw pointer to function: 230 milliseconds
wrapped pointer to function: 260 milliseconds
            wrapped closure: 220 milliseconds

http://coliru.stacked-crooked.com/a/73434861c73d5412

All that we can really say is that on most implementations, the overhead of forwarding a call through a std::function<> is negligible.
Topic archived. No new replies allowed.