Morse's Site
525 字
3 分钟
通过 RIME 学习 C++ 系列:3
2024-06-05

重载运算符 operator#

重载运算符的本质是函数,声明如下:

返回值 operator符号(参数) {

}

src/rime/algo/spelling.h 中代码

struct Spelling {
  string str;
  SpellingProperties properties;

  Spelling() = default;
  Spelling(const string& _str) : str(_str) {}

  bool operator==(const Spelling& other) { return str == other.str; }
  bool operator<(const Spelling& other) { return str < other.str; }
};

Spelling 重载了符号 ==<,方便对 Spelling 进行比较。const 修饰参数,表示不能修改。

类型转换操作符#

class Meter {
private:
    double length;
public:
    Meter(double len) : length(len) {}
    operator double() const { return length; }
};

int main() {
    Meter m(5.0);
    double len = m; // Here, the type conversion operator is used.
    std::cout << "Length in meters: " << len << std::endl;
    return 0;
}

在本例中,operator double() 是一个类型转换操作符,允许将 Meter 类型的对象转换为 double。在执行 double len = m; 这一行时,使用 operator double() 函数将 Meter 对象 m 隐式转换为 double,并将结果存储在 len 中。

在 rime 中这种语法也很常见,如:src/rime/config/config_types.h

...
class ConfigItemRef {
 public:
  ConfigItemRef(ConfigData* data) : data_(data) {}
  virtual ~ConfigItemRef() = default;
  operator an<ConfigItem>() const { return GetItem(); }
...

这里可以将 ConfigItemRef 类型变量转为 an<ConfigItem> 类型。

Boost 中事件管理 Signal 与 Slot#

src/rime/common.h 中有这样的代码:

using boost::signals2::connection;
using boost::signals2::signal;

using 是用来方便引用 connectionsignal,后续代码就可以直接使用 connectionsignal 类型了。

了解这些后,RIME 中用它来做什么呢?

boost::signals2 是事件管理框架,类似 Swift 中的 Combine 框架。这不过这里的把相关名词换成了 SignalSlot

Signal 相当于事件,Slot 相当于事件的订阅者。

void slotTest1(int a) {
  std::cout << "call slotTest1: " << a << std::endl;
}

void slotTest2(int a) {
  std::cout << "call slotTest2: " << a << std::endl;
}

struct HellWorld {
  void operator()(int a) const {
    std::cout << "HelloWorld: " << a << std::endl;
  }
};

int main(int argc, const char * argv[]) {

  boost::signals2::signal<void (int)> sig;

  sig.connect(slotTest1);
  sig.connect(slotTest2);

  HellWorld hello;
  sig.connect(hello);

  sig(100);


  return 0;
}

当然 slot 也可以回传值,当多个 slot 时,使用最后一个 slot 的值作为返回值。

在 RIME 中,用它来完成 Context 中的各种事件通知。

src/rime/context.h

class RIME_API Context {
 public:
  using Notifier = signal<void(Context* ctx)>;
  using OptionUpdateNotifier = signal<void(Context* ctx, const string& option)>;
  using PropertyUpdateNotifier =
      signal<void(Context* ctx, const string& property)>;
  using KeyEventNotifier =
      signal<void(Context* ctx, const KeyEvent& key_event)>;
...
通过 RIME 学习 C++ 系列:3
https://fuwari.vercel.app/posts/rime/rime_learn_03/
作者
Morse Hsiao
发布于
2024-06-05
许可协议
CC BY-NC-SA 4.0