首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将带有类型参数的结构作为函数参数传递?

如何将带有类型参数的结构作为函数参数传递?
EN

Stack Overflow用户
提问于 2017-02-06 09:56:19
回答 2查看 5.4K关注 0票数 2

如何将带有签名EcsClientimpl<P, D> EcsClient<P, D> where P: ProvideAwsCredentials, D: DispatchSignedRequest实例作为Rust中的引用传递给函数?因此,我的尝试是:

代码语言:javascript
复制
extern crate rusoto;

use std::default::Default;

use rusoto::{ DefaultCredentialsProvider, Region };
use rusoto::ecs::{ EcsClient };
use rusoto::default_tls_client;

fn get_task_definition_revisions(client: &EcsClient) {
    // Use EscClient instance here
}

fn main() {
    let provider = DefaultCredentialsProvider::new().unwrap();
    let client = EcsClient::new(default_tls_client().unwrap(), provider, Region::EuWest1).unwrap();

    get_task_definition_revisions(&client);

}

这给了我以下错误:

代码语言:javascript
复制
error[E0243]: wrong number of type arguments: expected 2, found 0
 --> src/main.rs:9:43
  |
9 | fn get_task_definition_revisions(client: &EcsClient) {
  |                                           ^^^^^^^^^ expected 2 type arguments

我试图修复这个问题是这样的:

代码语言:javascript
复制
extern crate rusoto;

use std::default::Default;

use rusoto::{
    DefaultCredentialsProvider,
    Region,
    ProvideAwsCredentials,
    DispatchSignedRequest
};
use rusoto::ecs::{ EcsClient, ListTaskDefinitionsRequest };
use rusoto::default_tls_client;

fn get_task_definition_revisions(client: &EcsClient<ProvideAwsCredentials, DispatchSignedRequest>) {
    // Use EcsClient instance here
}

fn main() {
    let provider = DefaultCredentialsProvider::new().unwrap();
    let client = EcsClient::new(default_tls_client().unwrap(), provider, Region::EuWest1);

    get_task_definition_revisions(&client);
}

这给了我:

代码语言:javascript
复制
error[E0277]: the trait bound `rusoto::ProvideAwsCredentials + 'static: std::marker::Sized` is not satisfied
  --> src/main.rs:14:1
   |
14 |   fn get_task_definition_revisions(client: &EcsClient<P, D>) {
   |  _^ starting here...
15 | |  let defs = client.list_task_definitions(&ListTaskDefinitionsRequest {
16 | |      family_prefix: None,
17 | |      max_results: None,
18 | |      next_token: None,
19 | |      sort: None,
20 | |      status: Some("ACTIVE".to_string()),
21 | |  });
22 | | }
   | |_^ ...ending here: the trait `std::marker::Sized` is not implemented for `rusoto::ProvideAwsCredentials + 'static`
   |
   = note: `rusoto::ProvideAwsCredentials + 'static` does not have a constant size known at compile-time
   = note: required by `rusoto::ecs::EcsClient`

error[E0277]: the trait bound `rusoto::DispatchSignedRequest + 'static: std::marker::Sized` is not satisfied
  --> src/main.rs:14:1
   |
14 |   fn get_task_definition_revisions(client: &EcsClient<P, D>) {
   |  _^ starting here...
15 | |  let defs = client.list_task_definitions(&ListTaskDefinitionsRequest {
16 | |      family_prefix: None,
17 | |      max_results: None,
18 | |      next_token: None,
19 | |      sort: None,
20 | |      status: Some("ACTIVE".to_string()),
21 | |  });
22 | | }
   | |_^ ...ending here: the trait `std::marker::Sized` is not implemented for `rusoto::DispatchSignedRequest + 'static`
   |
   = note: `rusoto::DispatchSignedRequest + 'static` does not have a constant size known at compile-time
   = note: required by `rusoto::ecs::EcsClient`

这感觉就像兔子洞我不应该掉下去的。

我还尝试更改函数签名以接受泛型,但是EcsClient是一个结构,而不是一个特征。谷歌并没有提供多少帮助,因为我不知道搜索的正确术语。

This question似乎意味着我应该能够声明一个像fn my_func(client: &EcsClient) { ... }这样的函数,并且它会工作,那么为什么上面的例子不能呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-06 12:29:38

问题是EcsClient不是类型,而是构建类型(也称为“类型构造函数”)的蓝图。

因此,当需要类型时,无论是函数还是结构成员,都不能只使用EcsClient;相反,每次都必须通过指定类型的泛型参数来使用它来构建类型。

因此,第一步是引入类型参数:

代码语言:javascript
复制
fn get_task_definition_revisions<P, D>(client: &EcsClient<P, D>) {}

但是,现在编译器会抱怨PD没有受到足够的约束:EcsClient只接受一种非常特定的PD

因此,下一步是查找PDEcsClient定义中指定的界限,并应用它们。在这一点上只是复制/粘贴:

代码语言:javascript
复制
fn get_task_definition_revisions<P, D>(client: &EcsClient<P, D>)
    where P: ProvideAwsCredentials,
          D: DispatchSignedRequest
{
}

然后你就成了黄金。

如果对于这个特定的函数需要更多的PD功能,可以通过使用+添加更多的边界来对它们进行适当的约束。

代码语言:javascript
复制
fn get_task_definition_revisions<P, D>(client: &EcsClient<P, D>)
    where P: ProvideAwsCredentials + 'static,
          D: DispatchSignedRequest
{
}

如果您想知道为什么Rust选择让您重复PD的界限,而它可以完美地推断它们,那是因为它关心您。更具体地说,它关心的是你6个月后,以及下一个维护者的到来。因此,如果你只写一次,读了很多次,它就会迫使你复制边界,这样以后你就不用想知道它们是什么了,并且递归地钻研每种类型/函数,这些类型/函数用来痛苦地聚合所有的片段。在Rust中,下一次阅读函数时,您将得到所有的信息。

票数 7
EN

Stack Overflow用户

发布于 2017-02-06 11:54:42

我不正确地理解了语法。PD似乎是占位符,就像T一样。我需要指定这些类型,因此签名现在如下所示:

代码语言:javascript
复制
fn get_task_definition_revisions<P: ProvideAwsCredentials, D: DispatchSignedRequest>(client: &EcsClient<P, D>) {
    ...
}

函数体中不使用PD,但必须声明它们。

完整的示例现在看起来如下:

代码语言:javascript
复制
extern crate rusoto;

use std::default::Default;

use rusoto::{
    DefaultCredentialsProvider,
    Region,
    ProvideAwsCredentials,
    DispatchSignedRequest
};
use rusoto::ecs::{ StringList, EcsClient, ListTaskDefinitionsRequest };
use rusoto::default_tls_client;

fn get_task_definition_revisions<P: ProvideAwsCredentials, D: DispatchSignedRequest>(client: &EcsClient<P, D>) {
    let res = client.list_task_definitions(&ListTaskDefinitionsRequest {
        family_prefix: None,
        max_results: None,
        next_token: None,
        sort: None,
        status: Some("ACTIVE".to_string()),
    });

    // ...
}

fn main() {
    let provider = DefaultCredentialsProvider::new().unwrap();
    let client = EcsClient::new(default_tls_client().unwrap(), provider, Region::EuWest1);

    get_task_definition_revisions(&client);
}

我仍然不完全确定为什么这是有效的或需要的,但我希望这个答案能帮助到其他人。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42064853

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档