0

I am begginer in C++ and I have the following template class:

template<typename... extensions>
class SomeServiceProxy
{
public:
void DoSomething() {std::cout<<"\ndoing sth\n";};
};

With the following pointer to function using "using" keyword

template<typename... extensions>
using DoSomethingFnPtr = void (SomeServiceProxy<extensions...>::*)();

And I am trying to put the method in a map and call it:

std::map<int, void*> myMap;



int main()
{
SomeServiceProxy<int> proxy;
DoSomethingFnPtr<int> memfnptr = &SomeServiceProxy<int>::DoSomething;
proxy.DoSomething();
(proxy.*memfnptr)(); //works
myMap[0]= &memfnptr;

auto it=myMap.find(0);
if(it != myMap.end() ){
SomeServiceProxy<int> proxy2;
(proxy2.&(it->second))(); //error
}



std::cout<<endl;
return 0;
}

What I get is : error: expected unqualified-id before ‘&’ token

Q: Is there any way to call the method using the map?

6
  • 3
    myMap[0]= &memfnptr; already makes no sense. You are not storing the member function pointer, you are storing a pointer to the member function pointer. In any case, if you are storing just a void* (or a member function pointer equivalent, since they cannot be cast to void*) with erased type in the map, then you need to cast it back to the original type before you can call it. How do you intend to use this map? Why is the type void*? Commented Jun 20, 2022 at 14:14
  • 2
    Most likely what you really want is a std::map<int, std::function<void()>> myMap; and then store this-capturing lambdas which call the member function in there. (But I am making some assumptions here. You should show the intended usage of the map.) Commented Jun 20, 2022 at 14:15
  • It's possible, but you need a cast and some more * and () sprinkled around: godbolt.org/z/f9vKGzjvx. Still, as user17732522 said, it doesn't make much sense to try that, you should show what are you trying to do instead of attempted solution. Commented Jun 20, 2022 at 14:24
  • as the error is not related to the ... extensions and you arent using them I suggest to start without them. Once it works without extensions you can still add them back in Commented Jun 20, 2022 at 14:26
  • You need to convert it to the correct type and dereference properly; (proxy2.*(*reinterpret_cast<DoSomethingFnPtr<int>*>(it->second)))(). (You can tell from how incomprehensible that is that you're heading down a bad path to whatever it is that you want to accomplish.) Commented Jun 20, 2022 at 14:31

1 Answer 1

1

A void* is not a member function pointer. And memfnptr is a member function pointer, you should store it in the map rather than a pointer to it.

This is your code made to compile with the most obvious fixes:

#include <map>
#include <iostream>

template<typename... extensions>
class SomeServiceProxy
{
public:
void DoSomething() {std::cout<<"\ndoing sth\n";};
};

template<typename... extensions>
using DoSomethingFnPtr = void (SomeServiceProxy<extensions...>::*)();


std::map<int, DoSomethingFnPtr<int>> myMap;



int main()
{
    SomeServiceProxy<int> proxy;
    DoSomethingFnPtr<int> memfnptr = &SomeServiceProxy<int>::DoSomething;
    proxy.DoSomething();
    (proxy.*memfnptr)(); //works
    
    myMap[0]= memfnptr;

    auto it=myMap.find(0);
    if(it != myMap.end() ){
        SomeServiceProxy<int> proxy2;
        (proxy2.*(it->second))(); //error
    }
    std::cout<<std::endl;
    return 0;
}

I suppose you want to store member function pointers for different instantiations of SomeServiceProxy in the same map and thats why you used void*. There are much better ways to do type erasure than using void*, though what is more or less universal with type erasure is: Erasing the type is the easy part. The difficult part is to restore the type when you need it. When you store member function pointers for different instantiations of SomeServiceProxy in the same map then you can only call them when you know what instantiation of the template it is.

The simple solution is to use a std::map<int, std::function<void()>> then store lambdas (or some other functor) that encapsulates the instance and the member function to be called. For example:

std::map< int , std::function<void()>> mymap;
mymap[0] = []() { 
    SomeServiceProxy<int> proxy;
    proxy.DoSomething();
};
mymap[0]();
Sign up to request clarification or add additional context in comments.

Comments

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.