我正在实现我自己的signal
/ slot(观察者模式,Qt样式)机制,所以我可以有一个property
来通知......那些已经改变了。< / p>
我认为C ++ 11提供了所有必要的功能,可以实现非常简洁和功能强大的实现。我遇到的“问题”是,如果我想“连接”到const
对象的信号,我需要signal::connect
函数为const,但修改回调列表/观察者。有两种直接解决方法:
const_cast
connect
内的列表。mutable
。在我看来,这两件事情都是一样的(之前已经问过,例如。{/ em>在this question中),并且在逻辑上非常精细,但风格上有问题。因此问题。有没有办法解决这个问题,或者这是对const_cast
/ mutable
的真正合理使用吗?
我现在拥有的一些预备代码:
template<typename... ArgTypes>
class signal
{
public:
template<typename Callable>
void connect(Callable&& callback) const
{
std::lock_guard<std::mutex> lock(slots_mutex);
slots.emplace_back(callback);
}
void emit(ArgTypes... arguments) const
{
std::lock_guard<std::mutex> lock(slots_mutex);
for(auto&& callback : slots)
{
callback(arguments...);
}
}
private:
// mutable here allows to connect to a const object's signals
mutable std::vector<std::function<void(ArgTypes...)>> slots;
std::mutex slots_mutex;
};
注意我没有测试过这段代码;这只是我当前心态的反映。
答案 0 :(得分:9)
mutable
通常是更好的选择。
尽可能避免(const
)投射,它很容易遇到未定义的行为,而mutable
保证不是 1)。
1 mutable
类成员保证不会转到例如.text
段的发射代码。
答案 1 :(得分:2)
有两种直接解决方法:
const_cast
connect
内的列表。- 制作列表
醇>mutable
。
实际上还有第三种选择(这是一种通用的可能解决方法,如果C ++没有提供mutable
关键字) - 您可以将相关数据移出语法对象:
class X
{
mutable int i1_;
// Data pointed to by i2_ semantically belongs to this object
// but doesn't constitute a syntactical part of it so it is not
// subject to const-correctness checks by the compiler.
std::unique_ptr<int> i2_;
public:
void constFunc() const {
i1_ = 123;
*i2_ = 456;
}
};
尽管有这个额外选项,我仍然同意πάντα ῥεῖ answer mutable
关键字是这种情况的正确选择。它以标准化的方式(例如允许被grepped)明确地记录该类的概念const
操作在技术上可能不是非变异的。例如,当关注类的const
函数的线程安全时,这很有用。
答案 2 :(得分:0)
signal :: connect 会修改 signal :: slot 。所以,我认为你唯一需要做的就是改变你的设计。让 signal :: connect 变为可变,并且调用者持有可变信号指针。