У меня есть общая функция foo
с некоторыми чертами комплексного характера:
use std::ops::Index;
// This trait is just as an example
trait Float {
const PI: Self;
fn from_f32(v: f32) -> Self;
}
// impl Float for f32, f64 ...
fn foo<C>(container: &C)
where
C: Index<u32>,
<C as Index<u32>>::Output: Float,
{
// ...
}
Теперь мне нужно использовать тип <C as Index<u32>>::Output
внутри функции связка (например, чтобы получить π через ::PI
или сказать ::from_f32(3.0)
).Но этот тип долго печатать вручную и делает весь код очень многословным и трудным для чтения.( Примечание : в моем реальном коде фактический тип еще длиннее и уродлив.)
Чтобы решить эту проблему, я попытался создать псевдоним локального типа функции:
// Inside of `foo`:
type Floaty = <C as Index<u32>>::Output;
Но это приводит к этой ошибке:
error[E0401]: can't use type parameters from outer function
--> src/lib.rs:16:20
|
10 | fn foo<C>(container: &C)
| --- - type variable from outer function
| |
| try adding a local type parameter in this method instead
...
16 | type Floaty = <C as Index<u32>>::Output;
| ^ use of type variable from outer function
Таким образом, как и другие элементы, псевдонимы type
также обрабатываются независимо от того, находятся они в функции или нет.Не имея хороших идей, я попытался написать макрос, который расширяется до типа:
// Inside of `foo`:
macro_rules! Floaty {
() => { <C as Index<u32>>::Output };
}
Floaty!()::PI; // errors
Хотя у меня был частичный успех с этим (Floaty!()
допустим в некоторых контекстах типа), эта последняя строка содержит ошибкис:
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `::`
--> src/lib.rs:20:14
|
20 | Floaty!()::PI; // errors
| ^^ expected one of `.`, `;`, `?`, `}`, or an operator here
error[E0575]: expected method or associated constant, found associated type `Index::Output`
--> src/lib.rs:17:17
|
17 | () => { <C as Index<u32>>::Output };
| ^^^^^^^^^^^^^^^^^^^^^^^^^
...
20 | Floaty!()::PI; // errors
| --------- in this macro invocation
|
= note: can't use a type alias as a constructor
Ни одна из моих попыток не сработала полностью. Можно ли не писать полное имя типа каждый раз?