C++ 实现 lambda 重载模式
大约 1 分钟
C++ 实现 lambda 重载模式
C++17 引入了结构化绑定和模板参数包展开,使得我们可以优雅地实现 lambda 重载模式。该模式常用于 std::visit 等需要对多种类型进行分派的场景。
1. 原理与实现
核心代码如下:
// 定义一个模板结构体,将多个 lambda 继承并展开 operator()
template <class... Ts> struct overloaded : Ts... {
    using Ts::operator()...;
};
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
- overloaded结构体通过多重继承,将所有 lambda 的- operator()合并。
- using Ts::operator()...;展开所有基类的调用运算符,实现多态调用。
- 最后一个模板推导指引,方便直接用花括号初始化。
2. 使用示例
以 std::variant 为例,结合 std::visit 实现多类型分派:
#include <iostream>
#include <string>
#include <variant>
struct A {
  int a;
  A(int a) : a(a) {}
  friend std::ostream &operator<<(std::ostream &os, const A &a) {
    os << "A: " << a.a;
    return os;
  }
};
int main() {
  std::variant<int, double, std::string, A> v = 42;
  auto print = overloaded{
      [](int i) { std::cout << "int: " << i << '\n'; },
      [](double d) { std::cout << "double: " << d << '\n'; },
      [](const std::string &s) { std::cout << "string: " << s << '\n'; },
      [](const A &a) { std::cout << "A: " << a << '\n'; },
      [](auto &&x) { std::cout << "unknown type: " << x << '\n'; },
  };
  std::visit(print, v);
  v = 3.14;
  std::visit(print, v);
  v = "Hello, world!";
  std::visit(print, v);
  v = A(42);
  std::visit(print, v);
  return 0;
}
/*
输出:
int: 42
double: 3.14
string: Hello, world!
A: 42
*/
3. 应用场景
- std::visit处理- std::variant多类型分派
- 事件分发、AST 访问器等需要多重重载的场景