Параметр типа ржавчины с HRTB

#rust

Вопрос:

У меня есть следующий тип

 struct Test<Args> {
  // ...
  phantom: PhantomData<Args>,
}
 

это должно хранить, наряду с содержимым, параметр типа для определения аргументов функции, которые будут переданы позже.

Я использую его следующим образом:

 #![feature(unboxed_closures, fn_traits)]
impl<Args> Test<Args> {
    fn update<F>(amp;mut self, args: Args, f: F)
    where
         F: FnOnce<Args>
    {
       //...
       let value = f.call_once(args);
       // ...
    }
}
 

К сожалению, я не могу использовать его для заимствованных ценностей. Мне нужно было бы уметь делать что-то вроде

 type MyTest = Test<for<'a> (amp;'a u32, amp;'a u32)>;
let mut t: MyTest = ...;
t.update((amp;5, amp;8), |lhs, rhs| lhs   rhs);
 

Но Test<for<'a> (amp;'a u32, amp;'a u32)> это неверный синтаксис.

В настоящее время мой обходной путь состоит в том, чтобы изменить Test вместо fn этого тип, а затем ограничить его рядом с другим типом на сайте вызова следующим образом:

 #![feature(unboxed_closures, fn_traits)]
struct Test<F> {
  // ...
  phantom: PhantomData<F>,
}

impl<F> Test<F> {
    fn update<Args, F2>(amp;mut self, args: Args, f: F2)
    where
         F: FnOnce<Args>,
         F2: FnOnce<Args>,
    {
       //...
       let value = f.call_once(args);
       // ...
    }
}

type MyTest = Test<for<'a> fn(amp;'a u32, amp;'a u32)>;
let mut t: MyTest = ...;
t.update((amp;5, amp;8), |lhs, rhs| lhs   rhs);
 

Но это относительно некрасиво и требует изменения публичного интерфейса. Я также не уверен, есть ли какие-либо проблемы с противопоставлением в его аргументах. fn

Есть ли лучший способ добиться этого, сохраняя оригинальную подпись (или близкую к ней)?

Я не хочу использовать сам сайт вызова F в универсальных типах, так как мне нужно, чтобы он был универсальным в методе, а не в типе, так как он может быть закрытием с заимствованными значениями, в то время как тип может быть статическим.

Ответ №1:

Способ выражения MyTest псевдонима типа выглядит следующим образом:

 type MyTest<'a> = Test<(amp;'a u32, amp;'a u32)>;
 

Комментарии:

1. К сожалению , мне нужно MyTest работать в течение каждой жизни 'a , а не в течение какой-то определенной жизни 'a , как в обходном пути, поэтому это не работает

2. @FilipeRodrigues Я вижу, вы хотите Test , чтобы вам ввели, что он будет принимать amp;T аргументы, которые являются общими в течение их жизни, так как они будут выведены на update() сайте вызова. К сожалению, я не думаю, что Rust поддерживает этот вариант использования; ваш синтаксис, вероятно, был бы подходящим для этого, если бы это было так.