3

我正在玩 Rust 的capnproto 库。因为 Rust 可以在某些情况下推断类型,所以我可以这样做:

let mut message = ::capnp::message::Builder::new_default();

无需知道消息的类型。如果我想将一个引用传递给message一个函数,我现在需要知道什么消息是让函数知道会发生什么。

一般有没有方便的方法来做到这一点?

到目前为止,我已经完成了以下工作:

let testing: () = message;

编译器错误失败:

error[E0308]: mismatched types
   --> src/main.rs:197:18
    |
197 |                 let temp: () = message;
    |                           ^^^^^^^ expected (), found struct `capnp::message::Builder`

但是当我键入注释我的函数时,如下所示:

fn example_fn(message: capnp::message::Builder) {...}

我收到如下错误:

error[E0243]: wrong number of type arguments: expected 1, found 0
  --> src/main.rs:72:32
   |
72 | fn dump_capnp_to_file(message: capnp::message::Builder, filename: &str) {
   |                                ^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument

错误:由于先前的错误而中止

我对来自 C++ 背景的 Rust 非常陌生;对不起,如果这是一个菜鸟问题!

4

1 回答 1

2

Rust不会在函数参数位置推断类型。这是设计使然,正如Rust 语言常见问题解答所述:

为什么不推断函数签名?

在 Rust 中,声明往往带有显式类型,而实际代码具有推断其类型。这种设计有几个原因:

  • 强制声明签名有助于在模块和 crate 级别强制执行接口稳定性。

  • 签名提高了程序员的代码理解能力,无需 IDE 在整个 crate 上运行推理算法来猜测函数的参数类型;它总是明确的和附近的。

  • 从机械上讲,它简化了推理算法,因为推理一次只需要查看一个函数。

由于capnp::message::Builder<A>需要一个类型参数A,因此您需要通过给出A一个值来限定参数的类型:

fn dump_capnp_to_file(message: capnp::message::Builder<SomeType>, filename: String) {
//                                                    ^^^^^^^^^^

否则使您的函数也通用,因此它可以接受任何类型A

fn dump_capnp_to_file<A>(message: capnp::message::Builder<A>, filename: String) {
//                   ^^^                                 ^^^

设定界限A

如果您选择最后一个选项,您可能需要额外的trait boundmessage来允许您在函数内部做不同的事情。例如,您可能想要发送message到另一个线程,这需要Builder<A>实现SendBuilder具有以下 impl(参考):

impl <A> Send for Builder<A> where A: Send + Allocator

这意味着Builder<A>可以实现Send,但只有在A实现Send和时Allocator。您可以对以下内容进行自己的约束(要求)A

fn dump_capnp_to_file<A>(message: capnp::message::Builder<A>, filename: String)
    where A: Send + Allocator
{
    // multi-threaded code...
}

或者(也许稍微好一点),Builder<A>直接绑定Send

fn dump_capnp_to_file<A>(message: capnp::message::Builder<A>, filename: String)
    where capnp::message::Builder<A>: Send

然后你将只能调用dump_capnp_to_file一个Builder实现Send

于 2017-05-01T19:17:37.137 回答