1

I'm programming a Discrete Event Simulator (DES) where events will be user programmed functions. I have a Class called UserEvents and a private member function called Add

    void Add(const void *Parameters, void *ReturnValue);

I'm trying to make a vector that would store the following struct:

 typedef struct FunctionPointerAlias { std::string FAlias; void(UserEvents::*FPointer)(const void*, void*); };

Based on a string, I want to call different functions. Thus switch would be nice but switch can't handle strings (and I don't want to hash my strings). So I made a vector with a struct (string Alias, FunctionPointer) and then I'll iterate over my vector looking for the user's inputed string, recovering the corresponding function pointer and calling it.

All user functions should be of type void, receiving parameters and returning values through void* pointers as such:

void UserEvents::Add(const void *Parameters, void *ReturnValue)
{
    int *A = (int*)Parameters;
    int *B = A;
    B++;

    int *C = (int*)ReturnValue;
    *C = *A + *B;

    //memcpy(ReturnValue, &C, sizeof(int));
    return;
}

(TL;DR) The problem lies when I try to call the function pointed by the function pointer. I get the error "Expression preceding parentheses of apparent call must have (pointer-to-) function type" on the line right above return in the "Add" if.

    void UserEvents::Choose(const std::string Alias, const void *Parameters, void *ReturnValue)
{
    if (Alias == "Example")
    {
        // *ReturnValue = Function(Parameters)
        return;
    }

    if (Alias == "Add") {
        void (UserEvents::*FunctionPointer)(const void*, void*) = &UserEvents::Add;
        (*FunctionPointer)(Parameters, ReturnValue);
        return;
    }
}
Pedro
  • 74
  • 1
  • 11
  • Helpful reading: https://isocpp.org/wiki/faq/pointers-to-members#macro-for-ptr-to-memfn – user4581301 Apr 03 '17 at 01:06
  • Your code doesn't seem to make much sense. Is `Add` meant to be a member function or not? If not, why is it? If so, how are you expecting to invoke it without an object on which to invoke it? – David Schwartz Apr 03 '17 at 01:20
  • @DavidSchwartz, Add is meant to be a member function. I'm not too sure on what you mean by _invoke it without an object on which to invoke it?_ I'm new to C++ and decided to use this uni project to learn it ^^ – Pedro Apr 03 '17 at 01:38
  • Honestly, it seems you don't understand what a member function is. For example, if you have a class called "Instrument", it might have a member function called "Play" which plays some particular instrument. But you have to have an instrument you want to play. You can't just call the `Play` function to play nothing in particular. A class member functions makes some particular class instance do something. There has to be some class instance. – David Schwartz Apr 03 '17 at 01:45
  • 2
    Possible duplicate of [C++ Call Pointer To Member Function](https://stackoverflow.com/questions/14814158/c-call-pointer-to-member-function) – phuclv Aug 07 '19 at 04:09

2 Answers2

4

I think the syntax to invoke that member function by pointer should be e.g.

( this->*FunctionPointer )( Parameters, ReturnValue );

C++ has two operators, .* and ->*, specifically created to access class members by pointer. Here's an article on the topic. The ubiquitous * operator just doesn't work with class member pointers.

Soonts
  • 20,079
  • 9
  • 57
  • 130
  • Same error ): E0109 expression preceding parentheses of apparent call must have (pointer-to-) function type line 39 UserEvents.cpp – Pedro Apr 03 '17 at 01:17
  • It worked, thanks! Could you enlighten me on why the `this->` is necessary? – Pedro Apr 03 '17 at 01:37
  • Well, that's the syntax of the language. C++ has two operators, ".*" and "->*", created to access class member by pointer. Here's some article about them: https://msdn.microsoft.com/en-us/library/k8336763.aspx The ubiquitous "*" operator just doesn't work with class member pointers. – Soonts Apr 03 '17 at 01:48
  • 1
    Member pointer can be used with any pointer to class instance, not just `this`. Hence the need to explicitly mention which class instance should be used. – Andrey Turkin Apr 03 '17 at 06:21
0

I didn't understand what you need very well, so I tried to do something general, you should use the pattern in your own class:

#include <iostream>
#include <string>

typedef void(*STR_FUNC)(const void*, void*);

struct FUNCTION_POINTER_ALIAS
{
    std::string FAlias;
    STR_FUNC fn;
};

void FN0(const void *Parameters, void *ReturnValue)
{
    std::cout << *(std::string*) Parameters << " FN0" << std::endl;
}

void FN1(const void *Parameters, void *ReturnValue)
{
    std::cout << *(std::string*) Parameters << " FN1" << std::endl;
}

void FN2(const void *Parameters, void *ReturnValue)
{
    std::cout << *(std::string*) Parameters << " FN2" << std::endl;
}

int main()
{
    FUNCTION_POINTER_ALIAS Items[] = {{"str0", FN0}, {"str1", FN1}, {"str2", FN2}};
    for (int i = 0; i < sizeof(Items) / sizeof(FUNCTION_POINTER_ALIAS); ++i)
        Items[i].fn(&Items[i].FAlias, NULL);
}
Ali Asadpoor
  • 327
  • 1
  • 13