2

In C++ I can write a template that takes a template parameter:

struct None;

template <class T>
struct FirstType {
    using type = None;
};

template <template <class...> class T, class Head, class... Tail>
struct FirstType<T<Head, Tail...>> {
    using type = Head;
};

This is impossible in Rust:

// doesn't work
trait FirstType {
    type Output;
}

impl<T, Arg> FirstType for T<Arg> {
//                           ^^^ type argument not allowed
    type Output = Arg;
}

But it's possible for the specific type:

struct Foo<T> {/* some stuff */}

impl<T> FirstType for Foo<T> {
    type Output = T;
}

I don't understand why we can implement a trait for any type T or for something like *mut T, but not for T<U>.

Is there any workaround?

trent
  • 25,033
  • 7
  • 51
  • 90
Michael Galuza
  • 386
  • 6
  • 16
  • Aren't you reinventing the [From trait](https://doc.rust-lang.org/std/convert/trait.From.html)? – Ivan C Nov 24 '20 at 22:50
  • 1
    If you have `struct Foo` and `type Bar = Foo`, then is ` as ReplaceType>::Output` equivalent to `Bar` (that is, `Foo`) or `Foo`? – trent Nov 24 '20 at 23:29
  • @IvanC no, no, my intention is to extract first (second etc) generic type parameters from struct or trait; I don't want to convert these types/traits themselves – Michael Galuza Nov 25 '20 at 06:41
  • @trentcl I'm wondering that such syntax is possible – Michael Galuza Nov 25 '20 at 06:42
  • @trentcl Sorry, [this](http://coliru.stacked-crooked.com/a/58b6310fa60502dc) works – Michael Galuza Nov 25 '20 at 17:20
  • 2
    See also [Is there an intrinsic reason explaining why Rust does not have higher-kinded-types?](https://stackoverflow.com/q/58092746/155423); [How do I make a structure generic in Rust without higher kinded type (HKT) support?](https://stackoverflow.com/q/41784344/155423); [Can a trait have a supertrait that is parameterized by a generic?](https://stackoverflow.com/q/56329170/155423). – Shepmaster Nov 25 '20 at 17:47
  • See also [Generic struct over a generic type without type parameter](https://stackoverflow.com/q/41508680/155423) – Shepmaster Nov 25 '20 at 17:56
  • 2
    It seems likely that you are suffering from the [X-Y problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). There's a problem you'd like to solve, you know how to solve it using the hammer known as C++, and now you want to know what the hammer is in Rust. However, there's probably a more effective tool in Rust that may or may not be a hammer. – Shepmaster Nov 25 '20 at 17:58
  • explain what this C++ is for, you can't drop a piece of code and expect people understand it without any context or a very good understanding of the language. – Stargateur Nov 25 '20 at 18:03
  • 1
    Thank you for editing the question. I feel that with the updated code, this question is answered by one or more of the questions Shepmaster linked. In short: no, being generic over a generic isn't possible in Rust (although GATs will enable it in some limited forms). However, I also agree with the other commenters that this kind of template metaprogramming isn't typical for Rust, and there's probably a more direct way to solve whatever problem you're working on. – trent Nov 25 '20 at 18:31
  • I'm still a little fuzzy on how exactly this could work if it did exist in Rust. The question I asked earlier about how it interacts with `type` aliases is one possible complication. It's possible what you're looking for is more along the lines of declarative macros, which are in some ways the closest Rust feature to C++ templates. – trent Nov 25 '20 at 19:03

0 Answers0