我想在模板类 task
中存储一个成员函数指针和一个相关的对象指针。然后我想做一个数组,在scheduler
类中调用这些成员函数。
但是,如果我将此类 task
保存在一个数组中,它们都需要具有相同的模板类型。这个障碍使得在任务类中保存对象指针变得毫无用处。
现在,我想知道是否有一种聪明的方法可以在相关的调度程序类中保护一组这样的对。如果我使用 std::tuple
,我无法在运行时遍历容器,或者至少不能以一种非常可读的方式进行迭代。
有没有解决方案,我不需要调度程序类的模板?
template <class Obj>
struct task {
typedef void (Obj::*task_fn_t)();
Obj* obj_ptr; // object referring
task_fn_t function; // member function
};
template <class Obj>
class scheduler {
task <Obj> *_tasks; // problem :(
};
最佳答案
使用 std::function<void()>
.
它几乎可以存储任何可以用 ()
调用的东西.从逻辑上讲,一个 Obj*
/成员函数指针合格(有一点包装)。
std::function<void()> f = [obj_ptr]{ obj_ptr->some_member_function(); };
std::function<Sig>
是一个多态值类型。它存储(按值)任何可以以与 Sig
兼容的方式调用的东西。 .在你的例子中,你想用零参数调用一些东西并丢弃它的返回值。这与 void()
兼容签名。
对于像成员指针和对象指针这样的小对象,它会在没有任何堆分配的情况下执行此操作。
在大多数情况下,避免动态分配 std::function
.
template<class..Args>
class scheduler {
task = std::function<void(Args...)>;
std::vector<task> tasks;
public:
void add_task( task t ) { tasks.push_back(std::move(t)); }
void operator()(Args...args) const {
for (auto&& t:tasks)
t(args...);
}
};
这不会让您删除任务。我们可以添加该功能:
template<class Key, class..Args>
class scheduler {
task = std::function<void(Args...)>;
std::map<Key, task> tasks;
public:
void add_task( Key const& k, task t ) {
tasks[k] = std::move(t);
}
void remove_task( Key const& k ) {
tasks.erase(k);
}
void operator()(Args...args) const {
for (auto&& t:tasks)
(t.second)(args...);
}
};
现在您可以使用 key 添加任务,并在您不想让它们运行时删除它们。 (请注意,它们将按 key 的顺序运行)。
scheduler<std::string> bob;
bob.add_task( "hello", []{std::cout << "hello\n";} );
bob.add_task( "world", []{std::cout << "world\n";} );
bob(); // runs both tasks
bob.remove_task( "world" );
bob(); // runs only the "hello" task
关于c++ - 为任务管理器封装成员函数指针的好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48754476/