我有以下回调系统
class ... {
...
std::vector<std::function<void()>> systemBringUps;
std::vector<std::function<void()>> systemTearDowns;
std::vector<std::function<void(EntityID_t)>> systemMains;
std::vector<std::function<bool(EntityID_t)>> systemChecks;
template <typename T>
void registerSystem() {
systemBringUps.push_back(T::systemBringUp);
systemTearDowns.push_back(T::systemTearDown);
systemMains.push_back(T::systemMain);
systemChecks.push_back(T::systemCheck);
T::onSystemRegister();
}
template <typename T>
void deregisterSystem() {
std::function<void()> bringUp = T::systemBringUp;
std::function<void()> tearDown = T::systemTearDown;
std::function<void(EntityID_t)> smain = T::systemMain;
std::function<bool(EntityID_t)> check = T::systemCheck;
std::remove(systemBringUps.begin(), systemBringUps.end(), bringUp);
std::remove(systemTearDowns.begin(), systemTearDowns.end(), tearDown);
std::remove(systemMains.begin(), systemMains.end(), smain);
std::remove(systemChecks.begin(), systemChecks.end(), check);
T::onSystemDeregister();
}
Run Code Online (Sandbox Code Playgroud)
该registerSystem
模板功能工作正常,但deregisterSystem
功能无法编译,说明
...
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/bits/predefined_ops.h:241:17: error: invalid operands to binary expression
('std::function<bool (unsigned short)>' and 'const std::function<bool (unsigned short)>')
{ return *__it == _M_value; }
~~~~~ ^ ~~~~~~~~
...
Run Code Online (Sandbox Code Playgroud)
所以似乎std::remove
无法编译,因为我定义的std::function
sderegisterSystem
是const
,而我试图从中删除的向量中的那些不是?有什么办法可以const
从这些std::function
s 中丢弃限定符吗?我试过使用复制构造函数
template <typename T>
void deregisterSystem() {
std::function<void()> bringUp(T::systemBringUp);
std::function<void()> tearDown(T::systemTearDown);
std::function<void(EntityID_t)> smain(T::systemMain);
std::function<bool(EntityID_t)> check(T::systemCheck);
std::remove(systemBringUps.begin(), systemBringUps.end(), bringUp);
std::remove(systemTearDowns.begin(), systemTearDowns.end(), tearDown);
std::remove(systemMains.begin(), systemMains.end(), smain);
std::remove(systemChecks.begin(), systemChecks.end(), check);
T::onSystemDeregister();
}
Run Code Online (Sandbox Code Playgroud)
但这以类似的方式失败。
您的问题不在于常量性,而是std::function
根本无法比较对象的相等性。你目前的方法根本行不通。
解决方案是在注册期间向调用者提供某种独特的“令牌”,可用于稍后取消注册。
您可以使用std::function<F>::target
直接获取保存的函数对象并进行比较。
例如,要删除所有功能T::systemBringUp
例如,要删除中systemBringUps
,您可以执行以下操作:
systemBringUps.erase(std::remove_if(systemBringUps.begin(), systemBringUps.end(), [](const auto& f) {
auto* target = f.template target<decltype(T::systemBringUp)>();
return target != nullptr && *target == T::systemBringUp;
}), systemBringUps.end());
Run Code Online (Sandbox Code Playgroud)
您可以创建一个辅助函数来检查 a 是否std::function
持有值:
template<class F, class T>
bool is_function_holding(const std::function<F>& func, const T& target) {
static_assert(std::is_assignable<std::function<F>&, const T&>::value, "Function could not possibly hold target");
auto* current_target = func.template target<typename std::decay<T>::type>();
return current_target != nullptr && *current_target == target;
}
// Later
systemBringUps.erase(std::remove_if(systemBringUps.begin(), systemBringUps.end(), [](const auto& f) {
return is_function_holding(f, T::systemBringUp);
}, systemBringUps.end());
systemTearDowns.erase(std::remove_if(systemTearDowns.begin(), systemTearDowns.end(), [](const auto& f) {
return is_function_holding(f, T::systemTearDown);
}, systemTearDowns.end());
// ...
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
102 次 |
最近记录: |