Allow static types to implement interfaces and appear as type arguments #8166
-
Now that interfaces can specify abstract static members, it's no longer meaningless to have a static class implement an interface or be used as a type argument. For example, the static classes public static class Vector128
{
public static Vector128<T> Abs<T>(Vector128<T> vector) where T : struct { /* ... */ }
public static Vector128<T> Add<T>(Vector128<T> left, Vector128<T> right) where T : struct { /* ... */ }
public static Vector128<T> AndNot<T>(Vector128<T> left, Vector128<T> right) where T : struct { /* ... */ }
// ...
}
public static class Vector256
{
public static Vector256<T> Abs<T>(Vector256<T> vector) where T : struct { /* ... */ }
public static Vector256<T> Add<T>(Vector256<T> left, Vector256<T> right) where T : struct { /* ... */ }
public static Vector256<T> AndNot<T>(Vector256<T> left, Vector256<T> right) where T : struct { /* ... */ }
// ...
}
public static class Vector512
{
public static Vector512<T> Abs<T>(Vector512<T> vector) where T : struct { /* ... */ }
public static Vector512<T> Add<T>(Vector512<T> left, Vector512<T> right) where T : struct { /* ... */ }
public static Vector512<T> AndNot<T>(Vector512<T> left, Vector512<T> right) where T : struct { /* ... */ }
// ...
}
public readonly struct Vector128<T> : IEquatable<Vector128<T>> where T : struct { /* ... */ }
public readonly struct Vector256<T> : IEquatable<Vector256<T>> where T : struct { /* ... */ }
public readonly struct Vector512<T> : IEquatable<Vector512<T>> where T : struct { /* ... */ } it might make sense for them all to implement the same CRTP interface: public interface IVectorOperations<TOperations>
where TOperations: IVectorOperations<TOperations>
{
abstract static TVector Abs<TVector, TElement>(TVector vector)
where TVector : IVectorIntrinsic<TVector, TOperations, TElement>
where TElement : struct;
abstract static TVector Add<T>(TVector left, TVector right)
where TVector : IVectorIntrinsic<TVector, TOperations, TElement>
where TElement : struct;
abstract static TVector AndNot<T>(TVector left, TVector right)
where TVector : IVectorIntrinsic<TVector, TOperations, TElement>
where TElement : struct;
}
public interface IVectorIntrinsic<TVector, TOperations, TElement> : IEquatable<TVector>
where TVector: IVectorIntrinsic<TVector, TOperations, TElement>
where TOperations: IVectorOperations<TOperations>
where T : struct
{
}
public static class Vector128 : IVectorOperations<Vector128> { /* ... */ }
public static class Vector256 : IVectorOperations<Vector256> { /* ... */ }
public static class Vector512 : IVectorOperations<Vector512> { /* ... */ }
public readonly struct Vector128<T> : IVectorIntrinsic<Vector128<T>, Vector128, T> where T : struct { /* ... */ }
public readonly struct Vector256<T> : IVectorIntrinsic<Vector256<T>, Vector256, T> where T : struct { /* ... */ }
public readonly struct Vector512<T> : IVectorIntrinsic<Vector512<T>, Vector512, T> where T : struct { /* ... */ } Unfortunately, C# won't let you do this, because static classes can't implement interfaces, and static classes can't appear as type arguments. (This is for good reasons, of course: a static type, unlike any other type, doesn't have a To address this, I'd like to propose where TOperations : static, IVectorOperations<TOperations> and then you could write generic methods that would operate on SIMD intrinsics of any size 🙂 |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
cc @tannergooding, as this relates to what we'd been discussing earlier |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
Previous discussions: #4840 #5517