-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generics programming using soa-derive #66
Comments
I made some progress in realizing the type refers to the derived pub struct SparseSet<T: StructOfArray> {
dense: Vec<EntID>,
sparse: Vec<u32>,
data: <T as StructOfArray>::Type,
} However, this still will not allow me to have generic implementations, as the following errors: pub fn new() -> Self {
Self {
dense: Vec::new(),
sparse: Vec::new(),
data: <T as StructOfArray>::Type::new(),
}
}
Do I have any alternatives? Any trait that implements the methods I need, so that I can have generic implementations? |
I see, I did find that PR, that commit was what helped me figure out part of it. If @mikialex can let me know if they've ever done generic implementations using their contribution, that would be really helpful. Otherwise I suppose I will look for an alternative, macros perhaps. |
I took a stab at this, but I ran into issues with lifetimes on associated types. pub trait SoAVec<'a, T: StructOfArray>: 'a {
type Ref<'t> where 'a: 't;
fn get<'t>(&'t self, index: usize) -> Option<Self::Ref<'t>> where 'a: 't;
fn index<'t>(&'t self, index: usize) -> Self::Ref<'t> where 'a: 't
...
}
impl<'a> SoAVec<'a, Particle> for ParticleVec {
type Ref<'t> = ParticleRef<'t> where 'a: 't;
fn get<'t>(&'t self, index: usize) -> Option<Self::Ref<'t>> where 'a: 't {
self.get(index)
}
fn index<'t>(&'t self, index: usize) -> Self::Ref<'t> where 'a: 't {
self.index(index)
}
...
} This looks like it works just fine until I try to use it in a mutable context, due to reborrowing, I think. This compiles: fn example<'a, V: StructOfArray, T: SoAVec<'a, V>>(vec: &'a T) -> Option<T::Ref<'a>> where T::Ref<'a>: PartialOrd {
let mut indices: Vec<_> = (0..vec.len()).collect();
indices.sort_by(|j, k| {
let a = vec.index(*j);
let b = vec.index(*k);
a.partial_cmp(&b).unwrap()
});
let i = indices.iter().position(|x| *x == 0).unwrap();
vec.get(i)
} This does not: fn example<'a, V: StructOfArray, T: SoAVec<'a, V>>(vec: &'a mut T) -> Option<T::Ref<'a>> where T::Ref<'a>: PartialOrd {
let mut indices: Vec<_> = (0..vec.len()).collect();
indices.sort_by(|j, k| {
let a = vec.index(*j); // Error here: argument requires that `vec` is borrowed for `'a`, `vec` does not live long enough
let b = vec.index(*k);
a.partial_cmp(&b).unwrap()
});
let i = indices.iter().position(|x| *x == 0).unwrap();
vec.get(i)
} If I use the real type though, everything is fine! Even when I use the trait method instead of the direct implementation: fn iter_max_concrete<'a>(vec: &'a mut ParticleVec) -> Option<<ParticleVec as SoAVec<'a, Particle>>::Ref<'a>> {
let mut indices: Vec<_> = (0..vec.len()).collect();
indices.sort_by(|j, k| {
let a = <ParticleVec as SoAVec<'a, Particle>>::index(&vec, *j);
let b = <ParticleVec as SoAVec<'a, Particle>>::index(&vec, *k);
a.partial_cmp(&b).unwrap()
});
let i = indices.iter().position(|x| *x == 0).unwrap();
vec.get(i)
} It's as though the compiler somehow relaxes the lifetime constraints given by the concrete implementation of |
So it seems that the issue is actually in the As a separate point, I'm not sure I understand why you wrote the trait with a lifetime parameter, instead of using GAT? // current
pub trait SoAVec<'a, T: StructOfArray>: 'a {
type Ref<'t> where 'a: 't;
fn get<'t>(&'t self, index: usize) -> Option<Self::Ref<'t>> where 'a: 't;
}
// GAT
pub trait SoAVec<T: StructOfArray> {
type Ref<'a> where Self: 'a;
fn get(&'_ self, index: usize) -> Option<Self::Ref<'_>> {
} |
Thank you for demonstrating I had put a lifetime on The top level trait I had written, slightly modified after adding your suggested changes. pub trait SoATypes: StructOfArray + Sized {
type Ref<'t> where Self: 't;
type RefMut<'t> where Self: 't;
type Ptr;
type PtrMut;
type Iter<'t>: Iterator<Item=Self::Ref<'t>> where Self: 't;
type Slice<'t>: SoASlice<
't,
Self,
Ref<'t> = Self::Ref<'t>,
Iter<'t> = Self::Iter<'t>,
Ptr = Self::Ptr,
> where Self: 't;
type SliceMut<'t>: SoASliceMut<
't,
Self,
Ref<'t> = Self::Ref<'t>,
Iter<'t> = Self::Iter<'t>,
RefMut<'t> = Self::RefMut<'t>,
IterMut<'t> = Self::IterMut<'t>,
Ptr = Self::Ptr,
PtrMut = Self::PtrMut,
> where Self: 't;
type IterMut<'t>: Iterator<Item=Self::RefMut<'t>> where Self: 't;
type Vec<'t>: SoAVec<
Self,
Ref<'t> = Self::Ref<'t>,
RefMut<'t> = Self::RefMut<'t>,
Ptr = Self::Ptr,
PtrMut = Self::PtrMut,
Slice<'t> = Self::Slice<'t>
> where Self: 't;
} I initially didn't put a lifetime on the The I might be better off decoupling the types such that there isn't one unifying trait and abandon the idea that all |
Hi, apologies for not being able to infer this from the documentation and code, I am not very experienced with these topics. Also, sorry if I get any terms wrong, either way, my question is the following:
Say I have a generic struct that is meant to include various types of SoAs. What trait bounds am I meant to use? Should T be a
Cheese
or aCheeseVec
?From my understanding of the documentation, you are meant to apply the trait bound
StructOfArray
, makingT
aCheeseVec
. However, that trait does not implement the usual methods (insert, pop, etc.), which would mean I can't do generic implementations. Is that the case, or did I miss something?If T is a SoA, how do I get the original type, for declaring function parameter types? For example, the function
get
makes use of thesparse
array to determine if an entity exists, after which it's meant to return the associated data, in this case aCheese
. What should?
be here, i.e. how do I getCheese
fromCheeseVec
in a generic way?Thank you.
The text was updated successfully, but these errors were encountered: