Box inverse traits / Where子句在框中

时间:2018-01-03 00:27:39

标签: generics rust

我遇到了无法在import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class CustomAdapter extends BaseAdapter { Context context; int icons[]; String[] carNames; LayoutInflater inflter; public CustomAdapter(Context applicationContext, int[] icons, String[] carNames) { this.context = applicationContext; this.icons = icons; this.carNames = carNames; inflter = (LayoutInflater.from(applicationContext)); } @Override public int getCount() { return icons.length; } @Override public Object getItem(int i) { return null; } @Override public long getItemId(int i) { return 0; } @Override public View getView(int i, View view, ViewGroup viewGroup) { view = inflter.inflate(R.layout.custom_spinner_layout, null); ImageView icon = (ImageView) view.findViewById(R.id.imageView); TextView names = (TextView) view.findViewById(R.id.textView); icon.setImageResource(icons[i]); names.setText(carNames[i]); return view; } } es和其他通用结构中使用where子句的问题。这对于通用通信添加很有用。 (A + B = B + A)。我想要实现的一个例子:

Box

这可以使用类型定义中的enum Foo<T> { Bar(Box<U where T: Add<U, Output = T>>), Baz(Box<U where T: Sub<U, Output = T>>), } 子句半成品:

where

enum FooHack<T, A, S> where A: Add<T, Output = T>, S: Sub<T, Output = T>, { Bar(A), Baz(S), Dummy(PhantomData<T>), // to stop the compiler from complaining } 的类型签名要求FooHackA为具体类型。是否有策略以便SA可以通用?

1 个答案:

答案 0 :(得分:2)

也许您已经意识到enter image description here了?这与您的目的完全匹配,T动态更改固定Add

但是,有两个问题阻止直接使用SubAdd作为特征对象:

  1. Subself不是对象安全的,因为它需要一个按值Self参数。
  2. 特质对象在RHS上是存在的,但你想要的特征对象存在于Add Sub / use std::ops::Add; trait MyAdd<T> { fn my_add(&self, other: T) -> T; } impl<T, U> MyAdd<T> for U where T: Add<U, Output = T>, U: Clone, { fn my_add(&self, other: T) -> T { other + self.clone() } } enum Foo<T> { Bar(Box<MyAdd<T>>), } {/ 1}}之上。
  3. 因此,您需要做额外的工作来介绍中间特征:

    U: Clone

    如果您不想T: Add<&'a U, Output = T>,可以根据您的使用情况选择:

    • 假设T: Add<U, Output = T>而不是self: Box<Self>
    • &self
    • 中使用fn my_add代替MyAdd<T>

    编辑:运算符重载

    上面的代理特征std::ops::Add本身并不代理操作员重载;因此,您必须为此手动实施// Coherence error impl<T> Add<Box<MyAdd<T>>> for T { type Output = T; fn add(self, other: Box<MyAdd<T>>) -> Self::Output { other.my_add(self) } }

    impl<T> Add<T> for TypeDefinedInTheSiblingCrate

    但是,由于一致性限制,此代码无法正常工作。这种限制是至关重要的,因为兄弟条件箱总是有可能有struct Wrapper<T>(T); impl<T> Add<Box<MyAdd<T>>> for Wrapper<T> { type Output = Wrapper<T>; fn add(self, other: Box<MyAdd<T>>) -> Self::Output { Wrapper(other.my_add(self.0)) } } 这样的impl,它肯定会与上面的impl重叠。

    一种可能的解决方法是使用trait objects

    Wrapper(x) + boxed_myadd_value + another_myadd_value

    然后你可以写{{1}}之类的东西。