简体   繁体   English

实现索引特征以返回一个不是引用的值

[英]Implementing Index trait to return a value that is not a reference

I have a simple struct that I would like to implement Index for, but as a newcomer to Rust I'm having a number of troubles with the borrow checker.我有一个简单的结构,我想为其实现Index ,但是作为 Rust 的新手,我在借用检查器方面遇到了许多麻烦。 My struct is pretty simple, I'd like to have it store a start and step value, then when indexed by a usize it should return start + idx * step :我的结构非常简单,我想让它存储一个开始和步长值,然后当由usize索引时它应该返回start + idx * step

pub struct MyStruct {
    pub start: f64,
    pub step: f64,
}

My intuition is that I'd simply be able to take the signature of Index and plug in my types:我的直觉是,我可以简单地获取Index的签名并插入我的类型:

impl Index<usize> for MyStruct {
    type Output = f64;

    fn index(&self, idx: usize) -> &f64 {
        self.start + (idx as f64) * self.step
    }
}

This gives the error mismatched types saying expected type &f64, found type f64 .这给出了错误mismatched types表示expected type &f64, found type f64 As someone who has yet to fully understand how Rust's type system works, I tried simply slapping & on the expression:作为尚未完全理解 Rust 的类型系统如何工作的人,我尝试简单地在表达式上加上&

fn index(&self, idx: usize) -> &f64 {
    &(self.start + (idx as f64) * self.step)
}

This now tells me that the borrowed value does not live long enough , so maybe it needs a lifetime variable?这现在告诉我, borrowed value does not live long enough ,所以也许它需要一个生命周期变量?

fn index<'a>(&self, idx: usize) -> &'a f64 {
    &(self.start + (idx as f64) * self.step)
}

The error is the same, but the note now gives lifetime 'a instead of lifetime #1 , so I guess that's not necessary, but at this point I feel like I'm stuck.错误是一样的,但注释现在给出了lifetime 'a而不是lifetime #1 ,所以我想这没有必要,但在这一点上我觉得我被卡住了。 I'm confused that such a simple exercise for most languages has become so difficult to implement in Rust, since all I want to do is return a computation from a function that happens to be behind a reference.我很困惑,对于大多数语言来说,这样一个简单的练习在 Rust 中变得如此难以实现,因为我想要做的就是从恰好位于引用后面的函数返回一个计算。 How should I go about implementing Index for a simple structure where the value is calculated on demand?我应该如何为按需计算值的简单结构实施Index

The Index trait is meant to return a borrowed pointer to a member of self (eg an item in a Vec ). Index trait 旨在返回一个借用的指向self成员的指针(例如Vec一个项目)。 The signature of the index method from the Index trait makes it impractical to implement it to have the behavior you described, as you'd have to store every value returned by index in self and ensure that the pointers remain valid until the MyStruct is dropped.来自Index trait 的index方法的签名使得实现它以具有您描述的行为是不切实际的,因为您必须将index返回的每个值存储在self并确保指针在MyStruct被删除之前保持有效。

This use case does not match the intuition for Index .此用例与Index的直觉不匹配。 When I see myStruct[3] , my intuition is that, just as for arrays, I'm getting a pointer to some already-initialized data.当我看到myStruct[3] ,我的直觉是,就像数组一样,我得到了一个指向一些已初始化数据的指针。 The interface for Index corroborates this intuition. Index的界面证实了这一直觉。

I can see two things that you might potentially be trying to achieve:我可以看到您可能试图实现的两件事:

  1. Getting nice indexing syntax for your datastructure.为您的数据结构获取良好的索引语法。

In this case I would recommend against the premise of implementing Index and just provide a method that returns a f64 instead of an &f64 like so.在这种情况下,我建议反对实现Index的前提,只提供一种返回f64而不是&f64

impl MyStruct {
    pub fn index(&self, idx: usize) -> f64 {
        self.start + (idx as f64) * self.step
    }
}

You don't get the operators, which is good because somebody reading [] would be mislead into thinking they were getting a pointer.你没有得到操作符,这很好,因为有人阅读[]会被误导,认为他们得到了一个指针。 But you do get the functionality you want.但是你确实得到了你想要的功能。 Depending on your use cases you may want to rename this method.根据您的用例,您可能希望重命名此方法。

  1. Passing MyStruct to a parameter with Index bounds.MyStruct传递给具有Index边界的参数。

This is trickier with good reason.这是有充分理由的棘手。 Index expects the data to be there before it asks for it. Index期望数据在它要求之前就在那里。 You can't generate and return it because index returns f64 , and you can't generate it in the datastructure and return a pointer because it doesn't take a &mut self .您无法生成并返回它,因为index返回f64 ,并且您无法在数据结构中生成它并返回一个指针,因为它不接受&mut self You'd have to populate these values before the call to index .您必须在调用index之前填充这些值。 Some redesign would be in order, and the direction of that redesign would depend on the larger context of your problem.一些重新设计将是有序的,重新设计的方向将取决于您的问题的更大背景。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM