如何在不使用 Box 的情况下从 trait 方法返回匿名类型? [英] How to return an anonymous type from a trait method without using Box?

查看:38
本文介绍了如何在不使用 Box 的情况下从 trait 方法返回匿名类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个扩展特性,它的方法只是适配器/组合器的简写:

I have an extension trait whose methods are just shorthands for adapters/combinators:

fn foo(self) -> ... { self.map(|i| i * 2).foo().bar() }

Trait::foo() 的返回类型是一些嵌套的Map<Foo<Bar<Filter...,包括闭包,因此对于所有的都是匿名的实用目的.我的问题是如何从特征方法返回这样的类型,最好不使用 Box.

The return type of Trait::foo() is some nested Map<Foo<Bar<Filter..., including closures, and is therefor anonymous for all practical purposes. My problem is how to return such a type from a trait method, preferably without using Box.

  • impl Trait 在返回位置将是要走的路,但尚未为 trait 方法实现此功能.
  • 返回一个 Box 是可能的,但我不想为每个被 trait 所缺少的适配器分配.
  • 我无法将匿名类型放入结构体并返回该结构体,因为 struct Foo<T>{ inner: T } 无法实现(我保证为所有 T 提供一个实现,但只返回一个特定的 Foo代码>).
  • 存在类型可能会解决上述问题,但它们将在一段时间内无法实现.
  • impl Trait in return position would be the way to go, yet this feature is not implemented for trait methods yet.
  • Returning a Box<Trait>is possible, yet I don't want to allocate for every adapter shorthanded by the trait.
  • I can't put the anonymous type into a struct and return that, because struct Foo<T> { inner: T } can't be implemented (I promise an impl for all T, yet only return a specific Foo<Map<Filter<Bar...).
  • Existential types would probably solve the above problem, yet they won't be implemented for some time.

我也可以避免这个问题并使用宏或独立函数;不过,这也让人感觉不卫生.

I could also just avoid the problem and use a macro or a freestanding function; this also feels unhygienic, though.

还有更多见解吗?

推荐答案

返回迭代器(或任何其他trait)? 涵盖了所有现有的解决方案.您没有使用过的方法是用函数指针替换闭包,然后使用类型别名(可选地包装在新类型中).这并不总是可行的,但由于您没有提供代码的 MCVE,我们无法判断这是否适合您:

What is the correct way to return an Iterator (or any other trait)? covers all the present solutions. The one you haven't used is to replace closures with function pointers and then use a type alias (optionally wrapping in a newtype). This isn't always possible, but since you didn't provide a MCVE of your code, we can't tell if this will work for you or not:

use std::iter;

type Thing<T> = iter::Map<iter::Filter<T, fn(&i32) -> bool>, fn(i32) -> i32>;

trait IterExt: Iterator<Item = i32> {
    fn thing(self) -> Thing<Self>
    where
        Self: Sized + 'static,
    {
        // self.filter(|&v| v > 10).map(|v| v * 2)
        fn a(v: &i32) -> bool { *v > 10 }
        fn b(v: i32) -> i32 { v * 2 }
        self.filter(a as fn(&i32) -> bool).map(b as fn(i32) -> i32)
    }
}

impl<I> IterExt for I
where
    I: Iterator<Item = i32>,
{}

fn main() {}

<小时>

老实说,在这些情况下,我会创建一个包装盒装 trait 对象的 newtype.这样,我就可以灵活地在内部以 API 兼容的方式使用非盒装选项重新实现它.


Honestly, in these cases I would create a newtype wrapping the boxed trait object. That way, I have the flexibility to internally re-implement it with a non-boxed option in an API-compatible fashion when it becomes practical to do so.

这篇关于如何在不使用 Box 的情况下从 trait 方法返回匿名类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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