我正在尝试实现以下代码模式。
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。如何定义可以注入更新函数的函数指针。
答案 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);
}
答案 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);
}
这在使用编译器优化时应该很可能现在内联,这实际上是首先使用crtp的重点: