天天看點

不允許dllimport函數的定義_Rust 不允許C++方式的函數重載overloading

不允許dllimport函數的定義_Rust 不允許C++方式的函數重載overloading

C++方式的函數重載,即同一個函數名以及多個不同的形參類型和個數(不包括傳回值類型), 以Ad-hoc(臨時,随時,不用事先深思熟慮)的方式來實作函數的重載!功能非常強大, 同時也是惹禍根源之一!

Rust 隻允許通過預先定義和實作Trait的方式來近似模拟C++ ad-hoc 函數重載!比如Rust允許部分運算符重載,比如:std::ops::Add Trait , 隻要為你的自定義類型實作了這個Add Trait 那麼你的自定義類型就可以執行加法運算,如: a+b 。

use std::ops::Add;
​
#[derive(Debug,Clone,Copy, PartialEq, Eq)]
struct Complex {
    real : i32,
    imag: i32,
}
​
impl Add for Complex {
    type Output = Complex;
​
    fn add(self, other: Complex) -> Complex {
        Complex {
            real: self.real + other.real,
            imag: self.imag + other.imag,
        }
    }
}
fn main() {
    let c1 = Complex{ real: 3, imag:7};
    let c2 = Complex{ real: 4, imag:6};
    println!("{:?}", c1 +c2); //對+運算符的重載。
}
​
           
  • 通過Rust Trait來模拟C++ ad-hoc函數重載

#[derive(Debug)]
enum IntOrFloat {
    Int(i32),
    Float(f32),
}
​
trait IntOrFloatTrait {
    fn to_int_or_float(&self) -> IntOrFloat;
}
​
impl IntOrFloatTrait for i32 {
    fn to_int_or_float(&self) -> IntOrFloat {
        IntOrFloat::Int(*self)
    }
}
​
impl IntOrFloatTrait for f32 {
    fn to_int_or_float(&self) -> IntOrFloat {
        IntOrFloat::Float(*self)
    }
}
​
fn attempt_4<T: IntOrFloatTrait>(x: T) {
    let v = x.to_int_or_float();
    println!("{:?}", v);
}
​
fn main() {
    let i: i32 = 1;
    let f: f32 = 3.0;
​
    //從表面上看,實作了同一個函數名和不同的參數類型。
    //從本質來說,它隻是通過trait來實作的自動類型轉換而已,隻是文法糖。
    //Rust官方也是通過trait來實作模拟函數重載的,包括運算符重載都是采用統一模式, 即定義和實作相應trait。
    attempt_4(i);
    attempt_4(f);
}
           

Rust 本質上禁止C++ ad-hoc 函數重載,因為坑太深!但是又通過trait來實作了一定的靈活性!如果再結合上泛型,那就會強大無比,而且更加安全可靠, 可謂嚴肅活潑!

我認為:所有權、生命周期、借用和Trait是Rust的靈魂特性。對于

Rust Trait

即可以幫你填平類型的差異,又可以幫你差異化定制,慢慢體會吧。

Rust 官方也是通過這種模式來模拟C++ ad hoc函數重載的!标準庫中很容易找到類似模式代碼。

#[derive(Debug)]
struct Foo {
    value:u64
  }
  
  trait HasUIntValue {
    fn as_u64(self) -> u64;
  }
  
  impl Foo {
    fn add<T:HasUIntValue>(&mut self, value:T) {
      self.value += value.as_u64();
    }
  }
  
  impl HasUIntValue for i64 {
    fn as_u64(self) -> u64 {
      return self as u64;
    }
  }
  
  impl HasUIntValue for f64 {
    fn as_u64(self) -> u64 {
      return self as u64;
    }
  }
  
  fn test_add_with_int()
  {
    let mut x = Foo { value: 10 };
    x.add(10i64);
    assert!(x.value == 20);
    println!("{:?}", x);
  }
  
    fn test_add_with_float()
  {
    let mut x = Foo { value: 10 };
    x.add(10.0f64);
    assert!(x.value == 20);
    println!("{:?}", x);
  }
​
​
fn main() {
    test_add_with_int();
    test_add_with_float();
}
​
           
萬變不離其宗,隻有明确實作了相應的

Trait

才可能具有相應的能力,才允許調用相應的函數方法, 進而有效避免了C++ ad-hoc函數重載的不可控和不明确問題。比如第三方庫提供了某函數,但是我們自己又定了自己的重載版本,或者是另一個第三方庫也提供了不同的重載版本, 那麼當程式運作起來時,到底調用的是哪個函數呢?是以C++ ad hoc 函數重載非常強大同時坑也深!而Rust隻能通過預先定義和實作

Trait

的方式來拓展功能, 避免了随意性,更加明确!因為

Trait

肯定不允許随便改動的。

對于函數重載Rust是明确拒絕的!因為泛型就可以搞定了, 比如上面的代碼例子,隻是針對一個參數的函數重載模拟, 那麼對于多參數函數怎麼辦呢? 其實泛型就可以搞定了!真的不太需要C++ ad hoc 函數重載了,因為兩者本質上都是去解決用同一套算法處理多種資料類型的問題。

  • Variadic可變長參數

Rust現在不直接支援函數可變長參數,但可通過宏來實作可變長參數,

宏: println!, vec!

就是典型例子, 另一些例子,如:

macro_rules! sum {
    ($($args:expr),*) => {{
        let result = 0;
        $(
            let result = result + $args;
        )*
        result
    }}
}
​
macro_rules! print_all {
    ($($args:expr),*) => {{
        $(
            println!("{}", $args);
        )*
    }}
}
​
fn main() {
    assert_eq!(sum!(1, 2, 3), 6);
    print_all!(1, 2, "Hello");
}
​
           
其實函數可變長參數并不是緊迫需要,通過數組參數類型之類也可達到相同目的!隻不過通過Rust宏機制實作看着更規矩安全些吧。
  • Reference

https://stackoverflow.com/questions/24857831/is-there-any-downside-to-overloading-functions-in-rust-using-a-trait-generic-f

https://stackoverflow.com/questions/24936872/how-do-i-use-parameter-overloading-or-optional-parameters-in-rust

https://stackoverflow.com/questions/25265527/how-can-i-approximate-method-overloading

https://doc.rust-lang.org/rust-by-example/macros/variadics.html

https://stackoverflow.com/questions/28951503/how-can-i-create-a-function-with-a-variable-number-of-arguments

https://doc.rust-lang.org/book/ch19-06-macros.html

《深入淺出Rust》 範長春著, 機械工業出版社
  • Author

學習随筆,如有謬誤,望請海涵雅正,謝謝。

作者:心塵了

email: [email protected]