函数指向模板化类方法的指针

时间:2017-01-17 08:50:50

标签: c++ c++14

我正在尝试实现以下代码模式。

struct Worker {
    void update(/* function pointer */) {

        for(unsigned int i = 0; i < 10; i++) {
            /* function execution */
        }
    }
}

template <typename t_derive>
struct BaseCrtp {
    void method1() {
        static_cast<t_derive*>(this)->method1();
    }

    void method2() {
        static_cast<t_derive*>(this)->worker.update(/*fptr of Derived1::method2*/);
    }
}

struct Derived1 : public BaseCrtp<Derived1> {
    Worker worker;

    void method1() {
        std::cout << "Derived1::method1" << std::endl;
    }

    void method2() {
        std::cout << "Derived1::method2" << std::endl;
    }
}

我想在Worker :: update的实例中调用Derived1的method2。如何定义可以注入更新函数的函数指针。

2 个答案:

答案 0 :(得分:3)

struct Worker {
    void update(/* function pointer */) {
     .....

Worker::update成为模板成员函数

struct Worker {
    template<typename Func>
    void update(Func&& func) {
     .....

或使用std::function

struct Worker {
    void update(std::function<void()> func) {
     .....

然后通过BaseCrtp<>::method2中的lambda传递回调,如下所示:

void method2() {
    static_cast<t_derive*>(this)->worker.update(
        [this]{ static_cast<t_derive*>(this)->method2(); }
    );
}

完整示例:

#include <iostream>
#include <functional>

struct Worker {

    template<typename Func>
    void update(Func&& func) {
        for(unsigned int i = 0; i < 10; i++) {
            func();
        }
    }

    //alternatively....
    //
    //void update(std::function<void()> func) {
    //    for(unsigned int i = 0; i < 10; i++) {
    //        func();
    //    }
    //}
};

template <typename t_derive>
struct BaseCrtp {
    void method1() {
        static_cast<t_derive*>(this)->method1();
    }

    void method2() {
        static_cast<t_derive*>(this)->worker.update(
            [this]{ static_cast<t_derive*>(this)->method2(); }
        );
    }
};

struct Derived1 : public BaseCrtp<Derived1> {
    Worker worker;

    void method1() {
        std::cout << "Derived1::method1" << std::endl;
    }

    void method2() {
        std::cout << "Derived1::method2" << std::endl;
    }
};

template<typename T>
void process(BaseCrtp<T>& t){
    t.method2();
}

int main(){
    Derived1 d1;
    process(d1);
}

herehere (std::function alternative)

答案 1 :(得分:1)

正如Martin Bonner建议我认为你可以使用包含Derived类的类型模板参数的Worker模板和带有指向你想要调用的方法的指针的非类型模板参数。这可以按如下方式完成:

template <class T, void (T::*)(void)>
struct Worker {
    void update(T *t) {
        t->method2();
    }
};

struct Foo {
  void method2() { }
  Worker<Foo, &Foo::method2> worker;
};

int main() {
    Foo foo;
    foo.worker.update(&foo);
}

[online demo]

这在使用编译器优化时应该很可能现在内联,这实际上是首先使用crtp的重点:

[godbolt]