【问题标题】:Defining generic Result<T, E> as return type将通用 Result<T, E> 定义为返回类型
【发布时间】:2015-09-04 12:45:02
【问题描述】:

我想创建一个 trait 强制在某些函数上返回 Result&lt;T, E&gt; 类型,但我无法弄清楚定义它的语法。

我已经做到了:

pub type NamedResult<T, E> = Result<T, E>;

pub trait Foo {
    fn bar<T, E>(&self) -> NamedResult<T, E>;
}

pub struct Thing;

impl Foo for Thing {
    pub fn bar<T, E>(&self) -> NamedResult<T, E> {
        Ok(78i32)
    }
}

产生以下错误:

error: mismatched types: 
    expected 'T', 
    found 'i32'
(expected type parameter, found i32) [E0308]

于是我尝试了:

pub fn bar<i32, String>(&self) -> NamedResult<i32, String> {
    Ok(78i32)
}

并收到以下错误:

error: user-defined types or type parameters cannot shadow the primitive types [E0317]

正确的语法是什么,以便我可以强制所述特征的实现者在某些函数上返回 Result&lt;T, E&gt; 类型?

【问题讨论】:

  • 为什么是NamedResult?那部分是一个完整的红鲱鱼。
  • @ChrisMorgan 一开始是NamedResult&lt;T&gt; = Result&lt;T, Error&gt;,但当我遇到第一批错误时,我就放弃了。

标签: generics rust traits


【解决方案1】:
fn bar<T, E>(&self) -> Result<T, E>;

这表示您有一个函数bar,给定任意类型TE,将返回Result&lt;T, E&gt;。请记住:用户指定类型。但是你方法的主体正在做的是返回一个Result&lt;i32, _&gt;,但i32不是T

如果希望指定将返回的类型,则需要在 trait 实现中指定,可以是泛型或(更通常)作为关联类型:

pub trait Foo {
    type Bar;
    type BarError;

    fn bar(&self) -> Result<Self::Bar, Self::BarError>;
}

pub struct Thing;

impl Foo for Thing {
    type Bar = i32;
    type BarError = ();

    pub fn bar(&self) -> Result<i32, ()> {
        Ok(78i32)
    }
}

这样,用户没有指定类型;相反,当您知道要在 Thing 上调用 bar 方法时,您就知道输出类型将为 Result&lt;i32, ()&gt;

【讨论】:

  • 如果使用Result&lt;T, E&gt;,实现该特征会是什么样子,类型可以是用户想要的任何类型?还是不能指定它必须返回一个Result,只返回一个类型定义的Result?
  • 最终,编译器必须知道返回类型有多大。函数必须具有在编译时已知的返回类型。
  • @nathansizemore:“无论用户想要什么”作为一个概念根本没有意义。你的代码必须以某种方式产生任何类型的值——它将如何做到这一点?
  • 好吧,我有一个相当愚蠢的想法,允许用户通过回调的方式初始化我的库,这将是一个错误回调,当发生错误时,我会将该错误传递给错误回调.使用上面的方法,它可以用于任何类型的错误或返回值,但是现在你已经指出了这一点,我可以看到它实际上是多么无用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多