Rust 函数的类型擦除

skg*_*nga 5 c++ rust

考虑这个 C++ 代码:

#include <iostream>
#include <functional>

using namespace std;

std::function<int(int, int)> foo(int c) {
  auto add = [] (int a, int b) { return a + b; };
  auto sub = [] (int a, int b) { return a - b; };
  if (c > 42) {
    return add;
  } else {
    return sub;
  }
}

int main() {
  cout << foo(100)(10, 20) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

两个 lambdas (addsub) 都通过类型擦除std::function,然后在 main 中调用该函数。我想知道如何在 Rust 中复制这种模式?

Iva*_*n C 6

您的示例的一个相当准确的翻译将是以下片段。

fn foo(c: i32) -> Box<dyn Fn(i32, i32) -> i32> {
    let add = |a, b| a + b;
    let sub = |a, b| a - b;
    Box::new(if c > 42 { add } else { sub })
}

fn main() {
    println!("{}", foo(100)(10, 20));
}
Run Code Online (Sandbox Code Playgroud)

一种类型的闭包是不可命名的,因此我们将其强制为 trait 对象并将其存储在堆上,据我所知,这与此大致相同std::function

  • 我认为 `std::function` 可以采用小尺寸优化,它将函数存储在自身内部而不是堆分配它。但由于其他要求,有时很难记住哪些类型不能进行这样的优化。 (2认同)
  • 请注意,由于闭包实际上并未借用其上下文,因此您可以将 `fn foo(c: i32) -&gt; &amp;'static dyn Fn(i32, i32) -&gt; i32` 作为签名,从而避免堆分配。尽管我们绑定到静态函数,但这仍然会擦除类型并动态分派。 (2认同)