Thread: Problem: passing function as argument !!!

  1. #1
    Registered User
    Join Date
    Jul 2009
    Posts
    15

    Problem: passing function as argument !!!

    Hi, I'm having a problem in pass a function as argument to another function.
    This call is made by reference, and the function called is declared into a class.
    A example of my problem is:

    Code:
    class ExClass {
           public:
                 int func(const int &); //***
    };
    
    int ExClass::func(const int &z) { return(z); }
    
    template <class T>
    void example(T &func) {}
    
    int main(){
         ExClass f;
         example( f.func );
         return(0);
    }
    When I compile that, I got such error:

    In function ‘int main()’:
    error: no matching function for call to ‘example(<unresolved overloaded function type>)’
    note: candidates are: void example(T&) [with T = int (ExClass::*)(const int&)]



    *** It's good to mention that if I declared "func" as "static int func(const int &);" into the "ExClass", I get no error. But I need let "func" be non-static.

    What am I supposed to do?
    Thank you.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You can't get from a "plain" function pointer to a pointer to member function, or back the other way. (Since a member function has to be called from an object of the class, and has to know about that object, etc., which a "plain" function pointer can't.)

    What are you trying to do, really?

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Hi, I'm having a problem in pass a function as argument to another function.

    It can't work because you're passing in a function that takes an implicit pointer to *this, which you haven't supplied, and without an object the function cannot be called, obviously.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    Registered User
    Join Date
    Jul 2009
    Posts
    15
    I'm intending to use a 'ready' function, Broydn, from 'Numerical Recipes Book". And that function, Broydn, calls aother function by reference. For example:
    Code:
    template <class T>
    void Broydn( T &func ) {}
    When my member function, "func", was declared as 'static', so I could use the syntax:
    Code:
    int main(){
         ExClass f;
         Broydn( f.func );
         return(0);
    }
    But, I can't understand why, if I declare my member function as non-static it doesn't work.

    Thank you.

  5. #5
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by tharnier View Post
    ...if I declared "func" as "static int func(const int &);" into the "ExClass", I get no error. But I need let "func" be non-static.
    I don't think you can do this without a static member. I tried a few different things on my own, and it seems you can't take the address of a non-static member function.

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Well, I had thought we had covered why: You would need an ExClass object to call your function with -- and Broydn quite simply won't have such an object, and therefore quite simply won't be able to call the function. What is this object ExClass doing for you? (I mean, I had to look up Broyden's method just now, and it appears to be a root-finder.) If you need this class, I suppose you can adjust your root-finder to take an object and a member function pointer, so that your root finder will have the object needed to call the function with.

  7. #7
    Registered User
    Join Date
    Jul 2009
    Posts
    15
    Quote Originally Posted by Elkvis View Post
    I don't think you can do this without a static member. I tried a few different things on my own, and it seems you can't take the address of a non-static member function.
    hmmmm, sorry if I was not clear. I think this explain why I couldn't do:

    Code:
    int main(){
        ExClass f, *p=&f;
        p -> func;
    ...
    }
    because I cant take the address of a non-static member function, am I right?

  8. #8
    Registered User
    Join Date
    Jul 2009
    Posts
    15
    Quote Originally Posted by tabstop View Post
    Well, I had thought we had covered why: You would need an ExClass object to call your function with -- and Broydn quite simply won't have such an object, and therefore quite simply won't be able to call the function. What is this object ExClass doing for you? (I mean, I had to look up Broyden's method just now, and it appears to be a root-finder.) If you need this class, I suppose you can adjust your root-finder to take an object and a member function pointer, so that your root finder will have the object needed to call the function with.
    ow yeah, I think you really helped me right here!!!
    Broydn is a root finder, you're right. And you let my problem clear; I need that Broydn be able to get an object from my class ExClass.
    But how should I do that?

    I thought that if I had declared Broydn as "friend" of "ExClass", so Broydn could use a member function even without a object, couldn't??
    Last edited by tharnier; 07-16-2009 at 12:59 PM.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Two examples.
    One using boost, the other without boost.
    Code:
    class ExClass 
    {
    public:
        int func(const int& z); //***
    };
    
    int ExClass::func(const int& z) { return z; }
    
    template <typename T>
    void example(T& func) { func(); }
    
    template <typename Class_t, typename Fnc_t>
    void example2(Class_t& Class, Fnc_t FncPtr) { (Class.*FncPtr)(); }
    
    int main()
    {
         ExClass f;
         example( boost::bind(&ExClass::func, f) );
         example2(f, &ExClass::func);
         return 0;
    }
    And don't forget to read this:
    https://apps.sourceforge.net/mediawi...arameter_names

    Quote Originally Posted by tharnier View Post
    I thought that if I had declared Broydn as "friend" of "ExClass", so Broydn could use a member function even without a object, couldn't??
    Of course not. That's just silly. Friends has nothing to do with it.
    The problem is that the functions are members OF objects. They are not global!
    So if you want to call a member function, you need to specify which class instance's member function you want to call!
    Thus you need the instance AND the member function pointer.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    What you're looking for is a 'functor'. In its crudest form it would work something like this:

    Code:
    class ExClass {
    	public:
            
    	int func(const int & value)
    	{
    		cout << "Value: " << value << endl;
    		return value;
    	}
    
            struct wrapper
    	{
    		wrapper(ExClass* this_)
    		: this_(this_)
    		{	}
    	
    		int operator ( )(const int & value)
    		{
    			return this_->func(value);
    		}
    		
    		ExClass* this_;
    	};
    	
    	wrapper wrap(void)
    	{
    		return wrapper(this);
    	}	
    };
    
    template <class T>
    void example(T &func) 
    {
    	int value = 10;
    	func(value); 
    }
    
    int main(void) {
    	ExClass
    		e;
    	ExClass::wrapper
    		f = e.wrap( );
    	example(f);		
    }
    Last edited by Sebastiani; 07-16-2009 at 01:51 PM. Reason: forgotten return values
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    In that case, I'll throw in another, better example:
    Code:
    class ExClass 
    {
    public:
        int func(const int& z); //***
    };
    
    int ExClass::func(const int& z) { return z; }
    
    template<typename Class_t, typename Fnc_t, typename Return_t>
    class Functor
    {
    public:
        Functor(Class_t& Class, Fnc_t FncPtr): m_Class(Class), m_FncPtr(FncPtr) { }
        Return_t operator () { return m_FncPtr(); }
        const Return_t operator () const { return m_FncPtr(); }
    
    private:
        Class_t m_Class;
        Fnc_t m_FncPtr;
    };
    
    template<typename Return_t, typename Class_t, typename Fnc_t>
    Functor<Class_t, Fnc_t, Return_t> FunctorWrapper(Class_t& Class, Fnc_t FncPtr)
    {
        return Functor<Class_t, Fnc_t, Return_t>(Class, FncPtr);
    }
    
    template<typename T> void example(T& Functor) { Functor(); }
    
    int main()
    {
         ExClass f;
         example( FunctorWrapper<int>(f, &ExClass::func) );
         return 0;
    }
    I'm not sure how it handles void return type, however. It may be that it needs extra work. Perhaps a specialization.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> I'm not sure how it handles void return type, however.

    AFAIK, it should handle that automagically. I could be wrong, though.

    >> const Return_t

    You probably shouldn't return const like that. The user might not want it to be, and anyway it wouldn't work if the type was already const. At any rate, yours is a much better way to handle a functor...I was just being lazy.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  13. #13
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by tharnier View Post
    I thought that if I had declared Broydn as "friend" of "ExClass", so Broydn could use a member function even without a object, couldn't??
    "friend" just means that it can access private variables of an object which it still needs to have -- you can't still talk about "the" variable x, it's bob's variable x, or fred's variable x, or joe's variable x, et cetera. Members don't exist by themselves, only as part of other objects (hence the name).

  14. #14
    Registered User
    Join Date
    Jul 2009
    Posts
    15
    Quote Originally Posted by Elysia View Post
    In that case, I'll throw in another, better example:
    I think that will work. But I'm just taking my time to understand the code....
    Thank you everyone.

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Sebastiani View Post
    >> I'm not sure how it handles void return type, however.

    AFAIK, it should handle that automagically. I could be wrong, though.
    I'm just concerned about returning void from the FncPtr call.

    >> const Return_t

    You probably shouldn't return const like that. The user might not want it to be, and anyway it wouldn't work if the type was already const. At any rate, yours is a much better way to handle a functor...I was just being lazy.
    That's why there are two overloads! One for const, one for non-const.
    It's critical if we pass the object through a const reference.
    So don't use "const" in the type and it'll work
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Passing A Function Into A Constructor
    By fourplay in forum C++ Programming
    Replies: 6
    Last Post: 03-15-2009, 06:06 AM
  2. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  3. Passing function as argument
    By NeMewSys in forum C Programming
    Replies: 16
    Last Post: 06-11-2008, 02:03 PM
  4. passing a function as an argument
    By angelscars in forum C++ Programming
    Replies: 6
    Last Post: 12-06-2005, 09:53 PM
  5. Replies: 5
    Last Post: 02-08-2003, 07:42 PM

Tags for this Thread