Rust 的 C++ ADL 重载函数替代方案?

Rust's alternative for C++ ADL overloaded functions?

有一个库提供通用函数和一些可使用的实现:

#include <iostream>

namespace lib {
  struct Impl1 {};
  struct Impl2 {};

  void process(Impl1) { std::cout << 1; }
  void process(Impl2) { std::cout << 2; }

  template<typename T> void generalize(T t) { process(t); }
}

我想通过外部代码扩展它。以下是 C++ 允许执行此操作的方式:

#include <lib.h> // the previous snippet

namespace client {
  struct Impl3 {};

  void process(Impl3) { std::cout << 3; }
}

int main() { // test
  lib::generalize(client::Impl3{}); // it couts 3
}

注意:lib 的代码对 client 的代码一无所知,并且仍然不执行动态调度。我怎样才能在我的 Rust 代码中实现同样的目标? (如果我不能,是否有类似的计划?)

当然,这正是 traits 的用途:

pub mod lib {
    pub trait Impl {
        fn process(&self);
    }

    pub struct Impl1 {}
    pub struct Impl2 {}

    impl Impl for Impl1 {
        fn process(&self) {
            println!("1");
        }
    }

    impl Impl for Impl2 {
        fn process(&self) {
            println!("2");
        }
    }

    pub fn generalize<T: Impl>(t: T) {
        t.process();
    }
}

mod client {
    pub struct Impl3 {}

    impl super::lib::Impl for Impl3 {
        fn process(&self) {
            println!("3");
        }
    }
}

fn main() {
    lib::generalize(client::Impl3 {});
}

Playground 上查看。

Rust 更严格,可能需要 lib 才能玩得很好。它可以通过定义一个 trait 来实现,该 trait 定义了支持 process:

的东西
trait Processable {
  fn process(self);
}

struct Impl1 {}
impl Processable for Impl1 {
  fn process(self) {/*TODO*/}
}

fn generalize<T: Processable>(t: T) { t.process(); }

然后,Processable可以被“外人”用来通知系统Impl3满足要求的接口:

struct Impl3 {}
impl Processable for Impl3 {
  fn process(self) {/*TODO*/}
}

那么,generalize也可以调用Impl3