将通用的Result<T, E>定义为返回类型

7

我希望创建一个trait,强制某些函数的返回类型为Result<T, E>,但我无法确定定义此内容的语法。

我已经做到了这一步:

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<T, E>类型?


为什么要使用NamedResult?那部分完全是一个干扰项。 - Chris Morgan
@ChrisMorgan 最初是 NamedResult<T> = Result<T, Error>,但在我得到第一批错误后,我就放弃了这种方式。 - nathansizemore
1个回答

8
fn bar<T, E>(&self) -> Result<T, E>;

这段话表示您有一个名为bar的函数,给定任意类型TE,将返回一个Result<T,E>。请记住:用户指定类型。但是,您的方法体正在返回Result<i32,_>,但是i32不是T
如果希望指定要返回的类型,则需要在特质实现中指定它,可以作为泛型或(更常见的)作为关联类型:
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<i32, ()>


如果要实现trait,使得Result<T, E>的类型可以是用户想要的任何类型,会是什么样子呢?或者说,是否不可能指定它必须返回一个Result,只能定义一个类型为Result的结果? - nathansizemore
最终,编译器必须知道返回类型的大小。函数必须在编译时具有已知的返回类型。 - Christopher Stevenson
3
“无论用户想要什么”并不是一个可行的概念。你的代码必须以某种方式生成任何类型的值-它将如何实现? - Chris Morgan
我有一个相当愚蠢的想法,允许用户通过回调来初始化我的库,其中一个回调是错误回调,当出现错误时,我会将该错误传递到错误回调中。使用上述方法,它可以用于任何类型的错误或返回值,但是现在你指出了这一点,我可以看到它实际上是毫无用处的。 - nathansizemore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接