Как реализовать специализированные версии универсальной функции?

Я хотел бы иметь несколько версий функции, оптимизированной для типа ее аргументов, и Rust вызывает соответствующую в зависимости от контекста.

В моем случае все аргументы имеют один и тот же тип, и все они эквивалентны, поэтому лучше избегать self аргумент.

Я пробовал этот код:

trait Foo<T> { 
    fn foo(a: T, b: T, c: T); 
}

impl Foo<i32> {
    fn foo(a: i32, b: i32, c: i32) {}
}

impl Foo<i16> {
    fn foo(a: i16, b: i16, c: i16) {}
}

fn main() {
    Foo::foo(1i32,2,3);
    Foo::foo(1i16,2,3);
}

но Rust требует аннотации типа:

ошибка: требуется аннотация типа: не удается разрешить _ : Foo<i32> [E0283]

Могу ли я избежать предоставления аннотаций типа на сайте вызова? Если мне нужно, как это сделать?

1 ответ

Решение

Помните, что вы всегда реализуете черту чего-то. Поэтому реализация черты всегда должна содержать for пункт:

impl SomeTrait for Something

Если нет for, то это не черта реализации. В твоем случае impl Foo<i32> не является реализацией Foo за i32 или что вы думаете; это неотъемлемое условие объявления метода для простого типа объекта Foo<i32>,

То, что вы на самом деле хотите, можно сделать, используя Self параметр типа:

trait Foo { 
    fn foo(a: Self, b: Self, c: Self); 
}

impl Foo for i32 {
    fn foo(a: i32, b: i32, c: i32) {}
}

impl Foo for i16 {
    fn foo(a: i16, b: i16, c: i16) {}
}

fn main() {
    Foo::foo(1i32,2,3);
    Foo::foo(1i16,2,3);
}

Этот код работает.

Обратите внимание, что сейчас Foo реализуется для определенного типа. Тип, для которого реализована черта, доступен через неявный Self введите параметр, и вы можете увидеть, как он используется в foo() декларация.

Другие вопросы по тегам