views:

1350

answers:

3

I want to convert function object to function.

I wrote this code, but it doesn't work.

#include <iostream>

typedef int (*int_to_int)(int);

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
    operator int_to_int () {
        return this->*&adder::operator();
    }
};

int main(void) {
    adder add_two(2);
    int_to_int add_fn = add_two;
    std::cout << add_two(3) << std::endl; // expect 5
    std::cout << add_fn(3)  << std::endl; // expect 5
    add_fn = adder(5);
    std::cout << add_fn(3)  << std::endl; // expect 8
    return 0;
}

and I got message from g++, says invalid use of non-static member function.

How do I get pointer to member function of instance?

Edit:My original problem is about Win32 API.

I'm forced to write windows program with old Win32 API at school. but I don't want to write horrible switch statement like some example codes on text. Then, I decided to write wrapper in C++.

I want to write the window class like ...

class Window {
public:
    LRESULT update (HWND, UINT, WPARAM, LPARAM);
    void run();
    // below methods are called by update()
    virtual void onclick(int, int);
    virtual void ondraw(); // ... and more methods
};

and I'm willing to write my application class with deriving this class and overloading some methods.

Finally, my actual probrem is how to do this in C++.

 // on initializing my window object,
 // I must register window class with callback which is 
 // not a C++ function object.
 // I try to explain what I want to do with psudocode mixing C++ and javascript.
 WNDCLASS wndclass;
 Window *self = this;
 wndclass.lpfnWndProc = function () {
     return self.update.apply(self, argunemts);
 };

In other word, I have to make closure into function pointer. I don't know how to do this, but I can't believe this can't do in C++.

Edit: The original title of this question was How to get pointer-to-member-function of instance. But this title and my question didn't tell my actual problem enough. Sorry to early answerers, and litb, thank you for suggestion and very useful answer!

+1  A: 

Instance method pointers are a bit tricky and are completely different beasts compared to 'normal' function pointers.

See what the C++ FAQ lite section 33 has to say about it. Also see this and this for concrete examples.

Henrik Gustafsson
A: 

A pointer to a nonstatic member function is different from a pointer to a static function (or to a global and thus static function) because nonstatic members have the hidden "this" parameter.

The type for globals or statics is something like int (*)(int)

However, the type for nonstatic is something like int (ClassName::*)(int).

That being said, your code has weirder things in it, since you seem to be trying to assign the constructor or a constructed object into your function pointer.

Uri
+3  A: 

Update: You told us what you want. I found this question here on SO: Best method for storing this pointer for use in WndProc . I'm not a Windows Programmer, but the Adam Rosenfield guy seem to be right in using SetWindowLongPtr and GetWindowLongPtr. So, you use it like this:

LRESULT CALLBACK my_callback(HWND hwnd, UINT ui, WPARAM wp, LPARAM lp) {
    Window * self = reinterpret_cast<Window*>(
        GetWindowLongPtr(hwnd, 0));
    return self->update(hwnd, ui, wp, lp); // handle it.
}

Register that function as the wnd-proc and store the this pointer of your Window object using SetWindowLongPtr. In the WNDCLASSEX structure, there is a cbWndExtra field that you assign sizeof(Window*) to, which is enough storage to just contain the this pointer. Then you can call

SetWindowLongPtr(my_hwnd, 0, reinterpret_cast<LONG_PTR>(this));

to put the this pointer into that region. Then receive it like the above and delegate to the real member function. You could in theory also use a static member function. But you have to be careful. Calling a static member function from C code can cause bugs, because the calling convention might be different between C code and C++ code. For Windows, that may not be an issue - I don't know. So better check yourself in addition.


The thing you try is invalid. You try to return a pointer to the function call operator, but there is no object provided when the call is made, beside that your conversion operator has the wrong type. The type that the conversion operator returns has function pointer type, but not member function pointer type. The closest you can get to is to use the proper type:

struct adder;
typedef int (adder::*int_to_int)(int);

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
    operator int_to_int () {
        return &adder::operator();
    }
};

Now, your conversion operator is not even considered, because it has to be called like this:

adder a(10); cout << (a.*(int_to_int)a)(2); // expected: 12

And manually like this:

// note, we just get the member function pointer using the conversion operator.
// Nothing is related to the actual temporary adder object. 
int_to_int i = adder(5);
cout << (adder(10).*i)(2); // expected: 12

The usual function call syntax does not cope with that. In short, what you try is not possible.

I think another question is, why the heck do you want to do that? I think we can help you better when we know what the original problem is. If you are trying to make it look and work like a function call, you don't need any conversion operators at all:

struct adder {
    int n_;
    adder (int n) : n_(n) {}
    int operator() (int x) { return x + n_; }
};

adder a(10); cout << a(2); // expected: 12
Johannes Schaub - litb
I edited my question with adding what I want to do. Thank you for suggestion to my question.
nwn