-1

I want to create an array of functions to member functions that have the same signature but are of different classes. (But they are inherited). I tried something like this and I understand why it doesn't work but how can I work around that and still be able to do this? I don't mind if for example the function doesnt exist on the object I pass (if it is of another class) since I have logic for that.

class Base 
{
public:
    virtual void BaseFunc();
};

class X : Base 
{
public:
    void XFunc();
};

class Y : Base
{
public:
    void YFunc();
};
int main()
{
    std::vector<std::function<void(Base*)>> v;
    v.push_back(&Base::BaseFunc); //OK
    v.push_back(&X::XFunc); //NOT OK
    v.push_back(&Y::YFunc); //NOT OK
}

I also tried having a template class that has a pointer to a member function of that class and then I would call from that class, but I can't have an array of templated class without giving the template argument(even if the class is simple and size doesn't depend on template argument). I also tried having the array just of void pointers but I found out that it is impossible to cast member function pointer to a void pointer.(I may not be right so if it is possible let me know)

Edit: To provide some background about my intent I'll paste my comment here: My idea is to let the user implement functions in a class that inherits a base class and then be able to pass these functions to my class which then stores them in an array and calls them on certain conditions that are specified.

Edit 2: I need a solution that is in c++11 or c++14

user0042
  • 7,917
  • 3
  • 24
  • 39
Kys Plox
  • 774
  • 2
  • 10
  • 23
  • 3
    This cannot work as `XFunc` and `YFunc` are not known to the base class, i.e. cannot be called with a pointer to `Base`. You'd have to make them (pure) virtual in the base class. – Henri Menke Dec 20 '17 at 20:13
  • My idea is to let the user implement functions in a class that inherits a base class and then be able to pass these functions to my class which then stores them in an array and calls them on certain conditions that are specified. – Kys Plox Dec 20 '17 at 20:16
  • Then you'd need something like `std::vector< std::variant< std::function, std::function, std::function > >`. Maybe open a textbook and review how inheritance works. – Henri Menke Dec 20 '17 at 20:17
  • 1
    More importantly, the signature `void X::XFunc()` is incompatible with `void(T*)` (for arbitrary types `T`). – Dietmar Kühl Dec 20 '17 at 20:22
  • But the first push works so doesn't that mean it is convertable? – Kys Plox Dec 20 '17 at 20:26
  • This looks a bit like a XY-problem. Why do you need such array of member functions at all, in preference of simple virtual (or even static) polymorphism? As for your edit: Make your exact use case clearer please. How do you actually intend to use `std::vector> v;`? – user0042 Dec 20 '17 at 20:27

1 Answers1

2

I think you’d need something akin std::mem_fn() but with the added flexibility of converting the object pointer. That should be straight forward to create:

template <typename R, typename X>
class open_mem_fun {
    R (X::*fn)();
public:
    open_mem_fun(R (X::*fn)()): fn(fn) {}
    template <typename T>
    R operator()(T* p) const {
        return (dynamic_cast<X&>(*p).*fn)();
    }
};
template <typename R, typename X>
open_mem_fun<R, X> open_mem_fn(R (X::*fn)()) {
    return open_mem_fun<R, X>(fn);
}

The resulting objects should be callable via a suitable std::function object:

std::function<void(Base*)>(open_mem_fn(&X::XFunc));
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • I got a `error C2440: '': cannot convert from 'open_mem_fun' to 'std::function'` – Kys Plox Dec 21 '17 at 11:53
  • 1
    @KysPlox: I typed the code on a phone and didn’t have easy access to a compiler. I added a missing template declaration but still can’t test easily. I’m pretty sure the overall approach works although it may need some fixing of typos. – Dietmar Kühl Dec 21 '17 at 12:06
  • 1
    @DietmarKühl I tested it just now and it works fine :) – Quentin Dec 21 '17 at 12:13
  • 1
    @Quentin: thank you for testing! Of course, I don’t know if this class template is actually useful for anything: personally I can’t imagine a use-case so far. – Dietmar Kühl Dec 21 '17 at 12:16
  • Yep it works now, I was trying to fix it in a wrong way.. Thank you very much! – Kys Plox Dec 21 '17 at 12:43