C++ c++;bool改变时的触发功能

C++ c++;bool改变时的触发功能,c++,boolean-logic,C++,Boolean Logic,我有一个不断流化的布尔值。我需要在bool变为true时触发一个函数,在bool变为false时触发另一个函数,但每次更改仅触发一次,因此我不能使用while(true)循环 什么是C++在观察值和触发时最好的方法?p> 谢谢。我将通过设置flagTrue变量和flagFalse变量来实现这一点。当遇到第一个True时,flagTrue将从false更改为True,并忽略所有后续True布尔值。类似地,当您遇到firat False时,flagFalse将从False变为True,并忽略以下所有

我有一个不断流化的布尔值。我需要在bool变为true时触发一个函数,在bool变为false时触发另一个函数,但每次更改仅触发一次,因此我不能使用
while(true)
循环

<>什么是C++在观察值和触发时最好的方法?p>
谢谢。

我将通过设置flagTrue变量和flagFalse变量来实现这一点。当遇到第一个True时,flagTrue将从false更改为True,并忽略所有后续True布尔值。类似地,当您遇到firat False时,flagFalse将从False变为True,并忽略以下所有False布尔值。此外,当所检查的布尔值从True更改为False时,您将把flagTrue更改为False,在另一种情况下也是如此。
例如:


看看观察者模式。您可以将布尔值封装在帮助器类中,该类在布尔值设置时触发事件

可观测布尔的示例实现:

#include <vector>

class Observer {
public:
    virtual void valueChanged() = 0;
};

class ObservableBool {
private:
    bool value;
    std::vector<Observer*> observers = std::vector<Observer*>();

public:
    bool getValue() {
        return value;
    }

    bool setValue(bool value) {
        bool changed = (value != this->value);
        this->value = value;
        if(changed) raiseEvent();
    }

    void addObserver(Observer* observer) {
        observers.push_back(observer);
    }

    void removeObserver(Observer* observer) {
        observers.erase(std::find(observers.begin, observers.end, observer));
    }

private:
    void raiseEvent() {
        for (int i = 0; i < observers.size; ++i) {
            observers[i]->valueChanged();
        }
    }
};
#包括
类观察员{
公众:
虚空值已更改()=0;
};
电子图书类{
私人:
布尔值;
std::vector observer=std::vector();
公众:
bool getValue(){
返回值;
}
布尔设置值(布尔值){
bool changed=(值!=此->值);
这个->值=值;
如果(更改)raiseEvent();
}
无效添加观察者(观察者*观察者){
观察员。推回(观察员);
}
无效移除观察者(观察者*观察者){
observators.erase(std::find(observators.begin,observators.end,observator));
}
私人:
void raiseEvent(){
对于(int i=0;i<0.size;++i){
观察者[i]->valueChanged();
}
}
};

这可以改进很多。一个非常好的方法是实现从bool到bool的隐式转换(但是要小心,重载bool的“=”运算符可能会很危险)。您可以将其模板化以支持任意类型,而不仅仅是bool,您应该使用智能指针而不是原始指针(
std::weak_ptr
最好),并且您可能应该使用函数指针来正确支持lambda,而不是Observer类。如果您做得正确,您可以像使用普通布尔值一样使用该类,在设置新值时会有很小的开销。默认情况下,对更改的所有反应都由更改值的线程执行。

我可能会从以下内容开始:

#include <functional>
#include <atomic>
#include <iostream>

struct trigger
{
  using closure_type = std::function<void()>;

  trigger(closure_type on_set, closure_type on_reset, bool initial_state = false)
  : _state { initial_state }
  , _on_set(std::move(on_set))
  , _on_reset(std::move(on_reset))
  {}

  void set() {
    if (not _state.exchange(true)) {
      _on_set();
    }
  }

  void reset() {
    if (_state.exchange(false)) {
      _on_reset();
    }
  }

  std::atomic<bool> _state;
  std::function<void()> _on_set;
  std::function<void()> _on_reset;
};

void has_set() {
  // you can marshall accross threads here by posting calls to a 
  // queue
  std::cout << __func__ << std::endl;
}

void has_unset() {
  // you can marshall accross threads here by posting calls to a 
  // queue
  std::cout << __func__ << std::endl;
}

int main()
{
  trigger t { has_set, has_unset };

  t.set();
  t.set();

  t.reset();
  t.reset();

}
#包括
#包括
#包括
结构触发器
{
使用closure_type=std::function;
触发器(集合上的闭合类型,复位上的闭合类型,布尔初始状态=false)
:_状态{初始状态}
,_在_集上(标准::移动(在_集上))
,_on_reset(标准::移动(on_reset))
{}
空集(){
if(非_state.exchange(true)){
_关于_集();
}
}
无效重置(){
如果(_state.exchange(false)){
_on_reset();
}
}
原子态;
std::函数集上的函数;
std::功能_on_重置;
};
void有_集(){
//您可以通过将调用发送到
//排队

std::cout派对有点晚了,但是如果你只是想把它搞定(比如测试),这里有一个稍微简单的解决方案:


这似乎比实现布尔包装类、触发器和观察者模式要简单一些。

查找感谢!(已编辑)因此相反的结果是:
if(bool==false&&flagflse==false){//DoSomething flagTrue=false;flagflse=True;}
是这样吗?我添加了初始化。我相信他们会让这更清楚。是的,你添加的相反内容是正确的。我已经更新了我的代码。请检查。啊,我明白了。这很有意义。再次感谢你!你不需要两个标志,一个就足够了:
静态bool isActive=false;bool newVal=read();if(newVal!=isActive){isActive=newVal;/*回调取决于isActive*/}
std::atomic::exchange在多线程环境中安全的同时为您提供以前的状态信息。
#include <functional>
#include <atomic>
#include <iostream>

struct trigger
{
  using closure_type = std::function<void()>;

  trigger(closure_type on_set, closure_type on_reset, bool initial_state = false)
  : _state { initial_state }
  , _on_set(std::move(on_set))
  , _on_reset(std::move(on_reset))
  {}

  void set() {
    if (not _state.exchange(true)) {
      _on_set();
    }
  }

  void reset() {
    if (_state.exchange(false)) {
      _on_reset();
    }
  }

  std::atomic<bool> _state;
  std::function<void()> _on_set;
  std::function<void()> _on_reset;
};

void has_set() {
  // you can marshall accross threads here by posting calls to a 
  // queue
  std::cout << __func__ << std::endl;
}

void has_unset() {
  // you can marshall accross threads here by posting calls to a 
  // queue
  std::cout << __func__ << std::endl;
}

int main()
{
  trigger t { has_set, has_unset };

  t.set();
  t.set();

  t.reset();
  t.reset();

}
/**
 * @brief Set a boolean variable.
 * @param b Pointer to the boolean variable.
 * @param value Set to this value.
 * @return Returns if the value was to be changed.
 */
bool set(bool* b, bool value)
{
    // if b isn't going to change
    if (*b == value) return false;

    // if b is going to change
    else
    {
        *b = value;
        return true;
    }
}

/**
 * @brief A possible implementation
 */
int main()
{
    bool my_variable = false;

    while(true)
    {
        // Set my_variable and flag it if it changed
        bool changed = set(&my_variable, some_function());

        // check for changed
        if (changed)
        {
            // ...
        }
    }
}