Трюк с перегрузкой функций - компилятор не может выбрать, какую функцию вызывать - PullRequest
0 голосов
/ 13 июля 2020

В Rust нет перегрузки функций: вы не можете определить несколько функций с одним и тем же именем, но с разными аргументами.

Однако я обнаружил следующий трюк, из-за которого создается впечатление, что существует перегрузка функций. Обратите внимание, как в main() я могу вызывать example.apply(...) с разными типами:

struct Example;

trait Apply<T, R> {
    fn apply(&self, value: T) -> R;
}

impl Apply<i32, i32> for Example {
    fn apply(&self, value: i32) -> i32 {
        value * 2
    }
}

impl Apply<&str, String> for Example {
    fn apply(&self, value: &str) -> String {
        format!("Hello, {}", value)
    }
}

fn main() {
    let example = Example;

    // Looks like function overloading!
    let one = example.apply(12);
    let two = example.apply("World");

    println!("{}", one);
    println!("{}", two);
}

Теперь я хотел бы создать две разные версии черты Apply: одну для значений, которые равны Copy и один для значений, отличных от Copy:

struct Example;

struct NotCopy(i32);

// For types which are Copy
trait ApplyCopy<T: Copy, R> {
    fn apply(&self, value: T) -> R;
}

// For types which are not Copy
trait ApplyRef<T, R> {
    fn apply(&self, value: &T) -> R;
}

impl ApplyCopy<i32, i32> for Example {
    fn apply(&self, value: i32) -> i32 {
        value * 2
    }
}

impl ApplyRef<NotCopy, String> for Example {
    fn apply(&self, value: &NotCopy) -> String {
        format!("NotCopy({})", value.0)
    }
}

Однако, когда я пытаюсь использовать это, я получаю ошибки:

fn main() {
    let example = Example;

    let one = example.apply(12);            // Error: multiple `apply` found
    let two = example.apply(&NotCopy(34));  // Error: multiple `apply` found

    println!("{}", one);
    println!("{}", two);
}

Одно из сообщений об ошибке:

error[E0034]: multiple applicable items in scope
  --> src/main.rs:30:23
   |
30 |     let one = example.apply(12);            // Error: multiple `apply` found
   |                       ^^^^^ multiple `apply` found
   |
note: candidate #1 is defined in an impl of the trait `ApplyCopy` for the type `Example`
  --> src/main.rs:16:5
   |
16 |     fn apply(&self, value: i32) -> i32 {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in an impl of the trait `ApplyRef` for the type `Example`
  --> src/main.rs:22:5
   |
22 |     fn apply(&self, value: &NotCopy) -> String {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #1
   |
30 |     let one = ApplyCopy::apply(&example, 12);            // Error: multiple `apply` found
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #2
   |
30 |     let one = ApplyRef::apply(&example, 12);            // Error: multiple `apply` found
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Компилятор жалуется, что не знает, какую apply функцию вызвать. Я ожидал, что он сможет сделать выбор: i32 не является ссылкой, а Copy, поэтому apply черты ApplyCopy - единственный, который может быть вызван, а &NotCopy(34) - это ссылка, а поскольку NotCopy не Copy, можно вызвать только apply из ApplyRef.

Это ограничение компилятора Rust или я что-то упустил?

1 Ответ

4 голосов
/ 13 июля 2020

Это ограничение компилятора Rust или я что-то упустил? ссылка по-прежнему является правильным типом , поэтому любой T может быть &Q под обложками, а ссылочные типы могут реализовывать черты.

Хотя NotCopy не является копией, &NotCopy равно Copy. Итак, &NotCopy соответствует обоим случаям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...