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';
}

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

回答

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

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));
}

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

  • I think `std::function` is allowed to employ a small size optimization where it stores the function within itself instead of heap allocating it. It's sometimes hard to remember which types can't do optimizations like that due to other requirements though.
  • Notice that since the closures do not actually borrow their context, you can do `fn foo(c: i32) -> &'static dyn Fn(i32, i32) -> i32` as your signature, avoiding a heap allocation. This will still erase the type and dynamically dispatch, although we are bound to static functions.

以上是Rust函数的类型擦除的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>