【问题标题】:Is it possible to write this Rust code into semantically equivalent C++ code?是否可以将此 Rust 代码写成语义等效的 C++ 代码?
【发布时间】:2014-11-23 02:17:37
【问题描述】:

我偶然发现了这个Rust example in Wikipedia,我想知道是否可以将其转换为语义等效的 C++ 代码?

程序定义了一个递归数据结构并在其上实现方法。递归数据结构需要一个间接层,它由一个唯一指针提供,通过box 运算符构造。 (这些类似于 C++ 库类型std::unique_ptr,尽管有更多的静态安全保证。)

fn main() {
    let list = box Node(1, box Node(2, box Node(3, box Empty)));
    println!("Sum of all values in the list: {:i}.", list.multiply_by(2).sum());
}

// `enum` defines a tagged union that may be one of several different kinds
// of values at runtime.  The type here will either contain no value, or a
// value and a pointer to another `IntList`.

enum IntList {
    Node(int, Box<IntList>),
    Empty
}

// An `impl` block allows methods to be defined on a type.

impl IntList {
    fn sum(self) -> int {
        match self {
            Node(value, next) => value + next.sum(),
            Empty => 0
        }
    }

    fn multiply_by(self, n: int) -> Box<IntList> {
        match self {
            Node(value, next) => box Node(value * n, next.multiply_by(n)),
            Empty => box Empty
        }
    }
}

显然在 C++ 版本中,Rusts enum 应该替换为 union,Rusts Box 应该替换为 std::unique_ptr 并且 Rusts Node tuple 应该是 std::tuple 类型,但我只是无法理解如何用 C++ 编写等效的实现。

我知道这可能不实用(而且绝对不是用 C++ 做事的正确方法),但我只是想看看这些语言的比较(C++11 的功能足够灵活,可以进行这种修补吗?)。我还想比较编译器生成的程序集的语义等效实现(如果可能的话)。

【问题讨论】:

  • 您是想用某种有效的 C++ 代码“按下”它,还是希望类似 C++ 的 C++ 代码做同样的事情?不知何故,你说的是两件事。
  • 是的,这是可能的,但是没有模式匹配,这很难看:coliru.stacked-crooked.com/a/4e4c80512fa9d739(当然有 C++ 中的模式匹配库。我在这里用“可怕的访问者模式”替换它。)
  • 什么是类 C++ 的 C++ 代码?通过“语义等价”,我的意思是 C++ 版本应该使用具有元组(整数值和下一个节点)和“空”指针作为其成员的联合来实现递归数据结构。当然为结构实现 sum() 和 multiply_by() 。这只是假设的示例,因此 C++ 版本可能既不惯用也不实用。
  • 当然,您也可以在 C++ 中编写稍有不同的代码,以完全避免模式匹配/访问者/联合的事情:coliru.stacked-crooked.com/a/2985c5a6c47c176f(尽管这要求 std::pair 与不完整的类型一起使用,这不保证)
  • @dyp [res.on.functions]/2? UB?

标签: c++ c++11 rust recursive-datastructures


【解决方案1】:

免责声明:我不是 C++11 专家。服用必要剂量的盐。

正如其他人评论的那样,有几种方法可以解释您的问题。我将采用过于激进的解释,因为这是唯一有趣的解释:

不可能将 Rust 代码翻译成等效的 C++ 代码。你能把它翻译成一个提供相同输出的程序吗?他们都是图灵完整的,所以你当然可以。您能否翻译它以保留原件中的所有语义?没有。

其中大部分可以被翻译,以保持实际行为。 Rust 风格的 enums 可以用带有标签字段和 unionstructs 替换,同时编写适当的运算符重载以确保正确销毁 only 的成员实际存储的变体。您可以(大概)以这样的方式使用unique_ptr,即首先分配内存,然后将新值直接写入分配,因此没有副本。我相信你可以重写fn sum(self),让它使用右值this(虽然我从来没有这样做过,所以我很容易出错)。

但据我所知,您不能在 C++ 中做的一件事是复制线性类型。没有办法静态强制移动的值不能再次使用。您可以做的最好的事情是运行时检查,这必然涉及额外的开销。这也解释了为什么你不能拥有一个不可为空的unique_ptr:你永远无法移动它,因为你必须让移动的变量处于可用状态。

现在,已经说过了,我应该通过指出 当前 来声明之前的声明,Rust 编译器会发出一些运行时检查以检查已删除(已移动)的值,以降旗的形式。我上次检查的计划是删除这些运行时检查以支持纯静态破坏,希望在 1.0 之前。

【讨论】:

  • 目前的计划并不是完全纯粹静态破坏。在可能的情况下,它是静态破坏,当有条件丢弃例如if cond { drop(foo) } 将在堆栈上创建一个布尔值来控制是否需要在外部范围的末尾删除 foo
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多