1

Looking at this answer I can see how to call a pointer to a member function by explicitly passing in this. However, what if I want the function passed in to be a member of the current object and to use the implicit this.

I've written this, which seems to work, but is it valid code, and is there a better way (C++14 or below) avoiding the dynamic_cast<>? Source on onlinegdb.com

#include <iostream>

class Base
{
    public:
        // From https://stackoverflow.com/a/9779391/1270789
        template<typename T, typename R>
        R proxycall(T *obj, R (T::*mf)(int))
        {
            return (obj->*mf)(42);
        }

        // My attempt
        template<typename T, typename R>
        R proxycall(R (T::*mf)(int))
        {
            return ((dynamic_cast<T *>(this))->*mf)(42);
        }
        
        virtual ~Base() {}
};

class Foo: public Base
{
    public:
        int doFoo(int x) { std::cout << "doing foo\n"; return x / 2; }
        int doCall() { return proxycall(this, &Foo::doFoo); } // OK
        int doNoThisCall() { return proxycall(&Foo::doFoo); } // Is this OK?
};

int main()
{
    Foo foo;
    std::cout << foo.doCall() << '\n';
    std::cout << foo.doNoThisCall() << '\n';

    return 0;
}
Ken Y-N
  • 14,644
  • 21
  • 71
  • 114
  • To be clear, `Base` is *not* supposed to be a CRTP class? – Davis Herring Mar 08 '22 at 05:49
  • @Davis No, it's not supposed to be, although I'm open to answers suggesting how it could be. My actual situation is that I need to use `std::bind(mf, dynamic_cast(this), _1)` to create a pointer to pass to a third-party library's callback. – Ken Y-N Mar 08 '22 at 06:09
  • Personal suggestions: hide the interface of `Base` and use `static_cast` for safe downcast. [demo](https://godbolt.org/z/4TMEdYMeb). Aside: would you mind showing me some practical usage of this tech? If I am understanding correctly, you not going to add `proxycall` as an interface, right? – Nimrod Mar 09 '22 at 02:12
  • If you are sure `T` derives from `Base`, you can do `static_cast(this)` and thus avoid `dynamic_cast`. (If you are not sure `T` derives from `Base`, then the original example will crash anyway when `dynamic_cast` returns `nullptr`). – Igor Tandetnik Mar 11 '22 at 15:08

0 Answers0