c++ - 简单的 rust 通用/模板添加功能

标签 c++ templates generics rust

所以我只是在学习 rust - 我已经设置了工具并让它们在结构上工作,交叉编译,链接库等等......我有 C++ 背景)。所以在 C++ 谈话中我想这样做:
C++

template<typename A, typename B>
auto add(A a, B b)
{
    return a + b;
}

int main() {
    std::cout << "add int int:    " << add(1, 2) << std::endl;
    std::cout << "add int double: " << add(1, 2.3f) << std::endl;
    std::cout << "add int float:  " << add(1, 2.3) << std::endl;
    std::cout << "add char int:   " << add('g', 2.3) << std::endl;
    std::cout << "add str str:    " << add(std::string("bob"), std::string("fred")) << std::endl;
}
输出:
add int int:    3
add int double: 3.3
add int float:  3.3
add char int:   105.3
add str str:    bobfred
这增加了“事物”。如果您尝试添加两个未实现正确的内容 +操作数正确的运算符,你会得到一个编译错误(比如添加一个字符串和一个整数) - 非常简单。
rust
现在使用rust (我完全没有掌握它。
普通添加功能
pub fn add(a: u64, b: u64) -> u64 {
    return a + b;
}
到目前为止还好。
尝试 1 将此模板化
我通过聆听错误并使用建议的更改(使用 std::ops::Add<Output = T> 我有点理解它,但我真的不知道为什么我必须指定这个。
pub fn add<T: std::ops::Add<Output = T>>(a: T, b: T) -> T
{
    return a + b;
}


println!("add int int:   {}", add(1, 2));    // ok
println!("add int float: {}", add(1, 2.3));  // fails to compile
这是意料之中的,因为我只告诉它一种类型......所以现在尝试两种类型 A,B - 但这是我迷路的地方:
pub fn add<A: std::ops::Add<Output = A>, B: std::ops::Add>(a: A, b: B) -> A
{
    return a + b;
}
我得到的错误是:
error[E0308]: mismatched types
  --> utils/src/lib.rs:19:16
   |
17 | pub fn add<A: std::ops::Add<Output = A>, B: std::ops::Add>(a: A, b: B) -> A
   |            - expected type parameter     - found type parameter
18 | {
19 |     return a + b;
   |                ^ expected type parameter `A`, found type parameter `B`
   |
   = note: expected type parameter `A`
              found type parameter `B`
   = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
所以现在我完全迷失了。首先,我似乎必须指定一个返回类型 - 但我希望为我推断出它。我怎么做?其余的错误可能都是由于返回类型为 A - 但我似乎必须指定一些东西......这里的任何帮助都会很棒! - 如果可能的话,我想存档与上述 c++ 模板相同的基本功能

最佳答案

首先,你最好引用 std::ops::Add 的文档。第一的。有一个 type Output您已设置,但还有一个模板参数 Rhs你也可以设置。所以你可以试试:

pub fn add_to_rhs<A, B>(a: A, b: B) -> B
  where A: std::ops::Add<B, Output = B>
{
    return a + b;
}
在那里你声明 LHS 值应该与 RHS 值相加,最后产生一种 RHS 值。但这仍然无法按您预期的那样工作
println!("add int float: {}", add_to_rhs(1, 2.3)); 
// fails to compile, no implementation for `{integer} + {float}`
这是合理的,因为弱类型不适合 Rust,因为它容易出现逻辑错误。什么是可能的解决方法?实际上类似于您在非通用程序中所做的事情——您将显式转换其中一个值:
pub fn add_to_rhs<A, B>(a: A, b: B) -> B
where A: Into<B>, B: std::ops::Add<Output = B>
{
    return a.into() + b;
}
这并没有达到与 C++ SFINAE 相同的灵活性(记住,没有弱类型),因为为了添加任何值,您需要制作两个版本的函数;我展示了一个变体,其中 LHS 值被转换并添加到 RHS 类型,但您也需要相反的方式。
而且由于我们在 Rust 中没有重载,所以这变得更不方便,你必须调用不同的函数并记住这一点。
编辑 :我玩了一点,并设法为不同类型的混合使用单一功能,但使用它部队你每次都指定一个返回类型
struct Adder<T>(std::marker::PhantomData<T>);
impl<T> Adder<T> {
    fn add<A, B>(a: A, b: B) -> T
      where T: std::ops::Add<Output = T>, A: Into<T>, B: Into<T> {
        return a.into() + b.into();
    }
}


println!("add int int:   {}", Adder::<i32>::add(1, 2));
println!("add int float: {}", Adder::<f64>::add(1, 2.3)); 
println!("add float int: {}", Adder::<f64>::add(2.3, 1));
结构体的目的是分隔 add的模板参数(可以完全推导出)从结果模板参数(您需要指定,否则返回类型不明确)

关于c++ - 简单的 rust 通用/模板添加功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63748118/

相关文章:

c++ - 将结构传递给函数

c++ - 在glm中重用矩阵?

c++ - Visual Studio : how to get output in "Win32" project

c++ - 在函数模板的声明部分中定义时,对任意类型属性的函数重载失败

arrays - typescript :数组类型取决于先前的数组元素

java - 如何检查 Fragment.onAttach() 内的类型化回调类型

c++ - 是否 move 分配一个 std::fstream 关​​闭原始流

c++ - C++ 函数模板中的参数可以转换吗?

c++ - 调用模板函数和非模板函数时的优先级是什么?

c# - 为抽象类中的集合设置值时遇到问题