如何从泛型函数返回具体类型? [英] How to return concrete type from generic function?

查看:55
本文介绍了如何从泛型函数返回具体类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的示例中, Default 特性仅用于演示目的.

In the example below the Default trait is used just for demonstration purposes.

我的问题是:

  1. f() g()的声明之间有什么区别?
  2. 为什么 g()不能编译,因为它与 f()相同?
  3. 如何从 impl trait 通用类型的声明中返回具体类型?
  1. What is the difference between the declarations of f() and g()?
  2. Why g() doesn't compile since it's identical to f()?
  3. How can I return a concrete type out of a impl trait generically typed declaration?

struct Something {
}

impl Default for Something {
    fn default() -> Self {
        Something{}
    }
}

// This compiles.
pub fn f() -> impl Default {
    Something{}
}

// This doesn't.
pub fn g<T: Default>() -> T {
    Something{}
}

推荐答案

f() g()的声明之间有什么区别?

What is the difference between the declarations of f() and g()?

  • f 返回某种实现 Default 的类型. f 的调用者不知道它将返回哪种类型.
  • g 返回某种实现 Default 的类型. g 的调用者可以选择必须返回的确切类型.
    • f returns some type which implements Default. The caller of f has no say in what type it will return.
    • g returns some type which implements Default. The caller of g gets to pick the exact type that must be returned.
    • 您可以清楚地看到在调用 f g 方面的区别.例如:

      You can clearly see this difference in how f and g can be called. For example:

      fn main() {
          let t = f(); // this is the only way to call f()
          let t = g::<i32>(); // I can call g() like this
          let t = g::<String>(); // or like this
          let t = g::<Vec<Box<u8>>(); // or like this... and so on!
          // there's potentially infinitely many ways I can call g()
          // and yet there is only 1 way I can call f()
      }
      

      为什么 g()不能编译,因为它与 f()相同?

      Why g() doesn't compile since it's identical to f()?

      它们是不相同的.编译 f 的实现是因为它只能以一种方式调用,并且始终会返回完全相同的类型. g 的实现无法编译,因为它可以为所有不同类型调用无数种方法,但始终会返回已损坏的 Something .

      They're not identical. The implementation for f compiles because it can only be called in 1 way and it will always return the exact same type. The implementation for g fails to compile because it can get called infinitely many ways for all different types but it will always return Something which is broken.

      如何从 impl trait 通用类型声明中返回具体类型?

      How can I return a concrete type out of a impl trait generically typed declaration?

      如果我正确地理解了您的问题,那您就不能.使用泛型时,让调用者确定函数必须使用的类型,因此函数的实现本身必须是泛型的.如果要在泛型函数中构造并返回泛型类型,通常的解决方法是将 Default 特性绑定到泛型类型上,并在实现中使用它:

      If I'm understanding your question correctly, you can't. When you use generics you let the caller decide the types your function must use, so your function's implementation itself must be generic. If you want to construct and return a generic type within a generic function the usual way to go about that is to put a Default trait bound on the generic type and use that within your implementation:

      // now works!
      fn g<T: Default>() -> T {
          T::default()
      }
      

      如果需要在函数中有条件地选择具体类型,则唯一的解决方案是返回特征对象:

      If you need to conditionally select the concrete type within the function then the only other solution is to return a trait object:

      struct Something;
      struct SomethingElse;
      
      trait Trait {}
      
      impl Trait for Something {}
      impl Trait for SomethingElse {}
      
      fn g(some_condition: bool) -> Box<dyn Trait> {
          if some_condition {
              Box::new(Something)
          } else {
              Box::new(SomethingElse)
          }
      }
      

      这篇关于如何从泛型函数返回具体类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆