- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
有几次,我遇到过可变引用和不可变引用都需要访问器方法的情况。
对于大约 3 行,复制逻辑不是问题,但是当逻辑变得更复杂时,复制粘贴大块代码就不好了。
我希望能够为两者重复使用代码。
Rust 是否提供了一些比复制粘贴代码或使用 unsafe
转换更好地处理这种情况的方法?
例如:
impl MyStruct {
pub fn get_foo(&self) -> &Bar {
// ~20 lines of code
// --- snip ---
return bar;
}
pub fn get_foo_mut(&mut self) -> &mut Bar {
// ~20 lines of code
// (exactly matching previous code except `bar` is mutable)
// --- snip ---
return bar;
}
}
这里是一个代码库的更详细的摘录,其中一个不可变的返回参数被强制转换为可变的,以支持一个函数的不可变和可变版本。这使用了包装指针类型(ConstP
和 MutP
用于不可变和可变引用),但函数的逻辑应该很清楚。
pub fn face_vert_share_loop<V, F>(f: F, v: V) -> LoopConstP
where V: Into<VertConstP>,
F: Into<FaceConstP>
{
into_expand!(f, v);
let l_first = f.l_first.as_const();
let mut l_iter = l_first;
loop {
if l_iter.v == v {
return l_iter;
}
l_iter = l_iter.next.as_const();
if l_iter == l_first {
break;
}
}
return null_const();
}
pub fn face_vert_share_loop_mut(f: FaceMutP, v: VertMutP) -> LoopMutP {
let l = face_vert_share_loop(f, v);
return unsafe {
// Evil! but what are the alternatives?
// Perform an unsafe `const` to `mut` cast :(
// While in general this should be avoided,
// its 'OK' in this case since input is also mutable.
l.as_mut()
};
}
最佳答案
( Playground 链接到使用 type parameters 和 associated types 的解决方案)
在这种情况下,&T
和&mut T
只是两种不同的类型。在不同类型上通用的代码(在编译时和运行时)是使用特征在 Rust 中惯用地编写的。例如,给定:
struct Foo { value: i32 }
struct Bar { foo: Foo }
假设我们想为 Bar
的 Foo
数据成员提供一个通用访问器。访问器应该在 &Bar
和 &mut Bar
上工作,适本地返回 &Foo
或 &mut Foo
。所以我们写一个trait FooGetter
trait FooGetter {
type Output;
fn get(self) -> Self::Output;
}
其工作是对我们拥有的特定类型的 Bar
进行通用化。它的 Output
类型将取决于 Bar
,因为我们希望 get
有时返回 &Foo
有时返回 &mut Foo
。另请注意,它使用 Self
类型的 self
。因为我们希望 get
在 &Bar
和 &mut Bar
上通用,所以我们需要为两者实现 FooGetter
,这样Self
具有适当的类型:
// FooGetter::Self == &Bar
impl<'a> FooGetter for &'a Bar {
type Output = &'a Foo;
fn get(self) -> Self::Output { & self.foo }
}
// FooGetter::Self == &mut Bar
impl<'a> FooGetter for &'a mut Bar {
type Output = &'a mut Foo;
fn get(mut self) -> Self::Output { &mut self.foo }
}
现在我们可以轻松地在通用代码中使用 .get()
来获取 &
或 &mut
对 Foo
的引用> 来自 &Bar
或 &mut Bar
(只需要 T: FooGetter
)。例如:
// exemplary generic function:
fn foo<T: FooGetter>(t: T) -> <T as FooGetter>::Output {
t.get()
}
fn main() {
let x = Bar { foo: Foo {value: 2} };
let mut y = Bar { foo: Foo {value: 2} };
foo(&mut y).value = 3;
println!("{} {}\n", foo(&x).value, foo(&mut y).value);
}
请注意,您还可以为 Bar
实现 FooGetter
,因此 get
对 &T
是通用的,&mut T
和 T
本身(通过将其移入)。这实际上就是 .iter()
方法在标准库中的实现方式,以及为什么它总是独立于其调用的参数的引用性做“正确的事情”。
关于reference - 如何避免在 Rust 中为可变和不可变引用编写重复的访问器函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48228667/
我之前让 dll 注入(inject)器变得简单,但我有 Windows 7,我用 C# 和 C++ 做了它,它工作得很好!但是现在当我在 Windows 8 中尝试相同的代码时,它似乎没有以正确的方
我正在尝试制作一个名为 core-splitter 的元素,该元素在 1.0 中已弃用,因为它在我们的项目中起着关键作用。 如果您不知道 core-splitter 的作用,我可以提供一个简短的描述。
我有几个不同的蜘蛛,想一次运行所有它们。基于 this和 this ,我可以在同一个进程中运行多个蜘蛛。但是,我不知道如何设计一个信号系统来在所有蜘蛛都完成后停止 react 器。 我试过了: cra
有没有办法在达到特定条件时停止扭曲 react 器。例如,如果一个变量被设置为某个值,那么 react 器应该停止吗? 最佳答案 理想情况下,您不会将变量设置为一个值并停止 react 器,而是调用
https://code.angularjs.org/1.0.0rc9/angular-1.0.0rc9.js 上面的链接定义了外部js文件,我不知道Angular-1.0.0rc9.js的注入(in
我正在尝试运行一个函数并将服务注入(inject)其中。我认为这可以使用 $injector 轻松完成.所以我尝试了以下(简化示例): angular.injector().invoke( [ "$q
在 google Guice 中,我可以使用函数 createInjector 创建基于多个模块的注入(inject)器。 因为我使用 GWT.create 在 GoogleGin 中实例化注入(in
我在 ASP.NET Core 1.1 解决方案中使用配置绑定(bind)。基本上,我在“ConfigureServices Startup”部分中有一些用于绑定(bind)的简单代码,如下所示: s
我在 Spring MVC 中设置 initBinder 时遇到一些问题。我有一个 ModelAttribute,它有一个有时会显示的字段。 public class Model { privat
我正在尝试通过jquery post发布knockoutjs View 模型 var $form = $('#barcodeTemplate form'); var data = ko.toJS(vm
如何为包含多态对象集合的复杂模型编写自定义模型绑定(bind)程序? 我有下一个模型结构: public class CustomAttributeValueViewModel { publi
您好,我正在尝试实现我在 this article 中找到的扩展方法对于简单的注入(inject)器,因为它不支持开箱即用的特定构造函数的注册。 根据这篇文章,我需要用一个假的委托(delegate)
你好,我想自动注册我的依赖项。 我现在拥有的是: public interface IRepository where T : class public interface IFolderReposi
我正在使用 Jasmine 测试一些 Angular.js 代码。为此,我需要一个 Angular 注入(inject)器: var injector = angular.injector(['ng'
我正在使用 Matlab 代码生成器。不可能包含代码风格指南。这就是为什么我正在寻找一个工具来“ reshape ”、重命名和重新格式化生成的代码,根据我的: 功能横幅约定 文件横幅约定 命名约定 等
这个问题在这里已经有了答案: Where and why do I have to put the "template" and "typename" keywords? (8 个答案) 关闭 8
我开发了一种工具,可以更改某些程序的外观。为此,我需要在某些进程中注入(inject)一个 dll。 现在我基本上使用这个 approach .问题通常是人们无法注入(inject) dll,因为他们
我想使用 swing、spring 和 hibernate 编写一个 java 应用程序。 我想使用数据绑定(bind)器用 bean 的值填充 gui,并且我还希望它反射(reflect) gui
我有这段代码,当两个蜘蛛完成后,程序仍在运行。 #!C:\Python27\python.exe from twisted.internet import reactor from scrapy.cr
要点是 Spring Batch (v2) 测试框架具有带有 @Autowired 注释的 JobLauncherTestUtils.setJob。我们的测试套件有多个 Job 类提供者。因为这个类不
我是一名优秀的程序员,十分优秀!