Captain'Flam
Captain'Flam

Reputation: 537

Calling a method from an other class using a method pointer

I'm passing a method pointer to a function template. It works for some method pointers, but not others.

I tried to help the compiler to differentiate types (declared args vs. passed args) using the tricky my_type_identity (thank to Jarod42) but I fails too.

Here is that minimal code that exposes the problem:

template<class T> struct my_type_identity { using type = T ;};

struct Spam
    {
    };

struct Eggs
    {
    void f0 ( Spam )         {}
    void f1 ( const Spam & ) {}
    };

template <class C> struct Bread
    {
    C c ;
    template <class F,class T> void apply1 ( void (F::*f)( T ), T t )                   { (c.*f)(t) ; }
    template <class F,class T> void apply2 ( void (F::*f)( T ), my_type_identity<T> t ) { (c.*f)(t) ; }
    };

int main ()
    {
    Spam  s ;
    Bread<Eggs> b ;
    b.apply1( &Eggs::f0,s ) ;
    b.apply1( &Eggs::f1,s ) ;  // error
    b.apply2( &Eggs::f0,s ) ;  // error
    b.apply2( &Eggs::f1,s ) ;  // error
    }

Upvotes: 0

Views: 83

Answers (2)

Captain&#39;Flam
Captain&#39;Flam

Reputation: 537

Finally a solution inspired by the one of suggested by JeJo seems to be good for me : It is compatible with c++11 and allows multiple parameters.

#include <iostream>

struct Spam
    {
    const char * foo ()       { return "mutable" ;}
    const char * foo () const { return "const" ;}
    };

struct Eggs
    {
    void f0()                          { std::cout << "f0()\n" ;}
    void f1(Spam s)                    { std::cout << "f1(" << s.foo()  << ")\n" ;}
    void f2(Spam& s)                   { std::cout << "f2(" << s.foo()  << ")\n" ;}
    void f3(Spam* s)                   { std::cout << "f3(" << s->foo() << ")\n" ;}
    void f4(const Spam* s)             { std::cout << "f4(" << s->foo() << ")\n" ;}
    void f5(const Spam& s)             { std::cout << "f5(" << s.foo()  << ")\n" ;}
    void f6(const Spam& s , int x )    { std::cout << "f6(" << s.foo()  << "," << x << ")\n" ;}
    int  f7(const Spam& s)             { std::cout << "f7(" << s.foo()  << ")\n" ; return 77 ;}
    };

template <class C> struct Bread
    {
    C c;
    template <class R=void,class F,class...P> R apply (F const&f,P&&...p)
        {
        return (c.*f)(p...) ;
        }
    };

int main()
    {
    Spam  s;
    Bread<Eggs> b;
    b.apply(&Eggs::f0);
    b.apply(&Eggs::f1,s);
    b.apply(&Eggs::f2,s);
    b.apply(&Eggs::f3,&s);
    b.apply(&Eggs::f4,&s);
    b.apply(&Eggs::f5,s);
    b.apply(&Eggs::f6,s,88);
    int x = b.apply<int>(&Eggs::f7,s) ;
    std::cout << "f7 -> " << x << std::endl ;
    }

Thanx you all!

Upvotes: 0

Jarod42
Jarod42

Reputation: 217398

In

template <class F,class T>
void apply ( void (F::*f)(T) , T t )

T might be deduced from both parameters, and should be identical. It is not your case.

You might change to

template <class F,class T>
void apply ( void (F::*f)(T) , std::type_identity_t<T> t )

to only deduce from first parameter.

Upvotes: 3

Related Questions