1

In trying to implement a suggested answer here in my own context, I am running into a compilation error.

Consider code:

#include <iostream>

class SIMPLE {
public:
    SIMPLE() { for (int i = 0; i < 5; i++) val[i] = 5; };
    int retval(int index) { return val[index]; }
private:
    int val[5];
};

void print_array_of_length5(int (*fnptr)(int index)){
    for (int i = 0; i < 5; i++)
        printf("%d ", fnptr(i));
}

int global_array[5] = { 0, 1, 2, 3, 4 };
int global_function(int index){
    return global_array[index];
}

int main(){
    print_array_of_length5(&global_function);//Works fine.
    int (SIMPLE::*p)(int) = &SIMPLE::retval;//Following method suggested in the answer above
    class SIMPLE smpl;
    print_array_of_length5(smpl.*p);//Compile error: a pointer to a bound function may only be used to call the function
}

The function works when supplied with the address of a global function. It does not work when passed smpl.*p analogous to the method suggested. How should one fix this error?

2
  • 2
    The print_array_of_length5 function take a pointer to a non-member function. Commented Sep 10, 2021 at 15:20
  • 2
    You cannot call a non-static member function without an instance and there is no instance available in print_array_of_length5 - you have to rethink your entire approach Commented Sep 10, 2021 at 15:23

2 Answers 2

4

You need another overload for print_array_of_length5 in order to pass a member function pointer:

template<typename T>
void print_array_of_length5(int (T::*fnptr)(int index), T& obj)
{
    for(int i = 0; i < 5; ++i)
    {
        printf("%d ", (obj.*fnptr)(i));
    }
}

int main()
{
    SIMPLE smpl;
    print_array_of_length5(&SIMPLE::retval, smpl);
}
Sign up to request clarification or add additional context in comments.

2 Comments

I tested this approach and this works. However, one would need to replicate the code inside of print_array_of_length5 twice -- one with a single argument and another with two arguments, don't you think? In @NathanOliver's answer, it appears only one function needs to be maintained.
In speak of maintenance: The @NathanOliver's implies the need to type validations, which is enough to take things complex. And BTW, the usage of the function in the question is not clear.
2

You can't pass a non-static member function pointer as a regular function pointer. Member functions have access to the this pointer, and the way they get that is via an invisible implicit function parameter. You need to have the object on which to call the function, and the function itself, be bound together, which a function pointer simply can't do.

What we can do is make print_array_of_length5 a function template, and allow it to take any type of callable. That would give you something like this:

template <typename Function>
void print_array_of_length5(Function func){
    for (int i = 0; i < 5; i++)
        printf("%d ", func(i));
}

To call it with a non-static member function, you can use a lambda expression, or std::bind(), like this:

SIMPLE smpl;
print_array_of_length5([&smpl](int foo){ return smpl.retval(foo); });
using namespace std::placeholders;
SIMPLE smpl;
auto func = std::bind(&SIMPLE::retval, &smpl, _1);
print_array_of_length5(func);

3 Comments

I worked further with this answer trying to implement this in my more complicated project where I have an OUTER class in one of whose method a different INNER class object's method should be pass as a function pointer. I am running into a compilation issue there. Would it be possible for you to take a look at this link which shows the compiler error to suggest a way out? godbolt.org/z/rG1oc86z5 If that is too much to ask, I can understand. I will post a new question on SO.
@Tryer You forgot to give the function parameter a name in the definition: godbolt.org/z/MK3sGx1hY
Ah yes. Sorry I am extremely new to templates, etc. Thank you again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.