У меня есть общая структура в ржавчине, которая имеет одно общее поле, в данном случае вал и поле для конкретного типа:
struct A<T> {
val: i32,
t: T
}
Что я пытаюсь сделать, так это иметь метод, связанный со структурой, независимо от типа Т. Что-то, что я могу назвать так:
A::my_method()
Вместо:
A::<T>::my_method()
Я попытался реализовать трейт Получить на А<Т> и назвать его следующим образом:
struct A<T> {
val: i32,
t: T
}
trait Get {
type ValType;
fn get_val() -> Self::ValType;
}
impl<T> Get for A<T> {
type ValType = i32;
fn get_val() -> Self::ValType {
2
}
}
fn main() {
let a = A {
val: 2,
t: 3.0
};
// This is the call I want, if possible
println!("{:?}", A::get_val());
}
Проблема в том, что он не компилируется, чего и следовало ожидать. Результат, который я хочу, выглядит примерно так:
impl<T> Get for A<any T> {
type ValType = i32;
fn get_val() -> Self::ValType {
2
}
}
В некоторых сообщениях я обнаружил, что обходной путь состоит в том, чтобы иметь параметр фиктивного типа и вызывать мою функцию следующим образом:
struct DummyType;
fn main() {
let a = A {
val: 2,
t: 3.0
};
// This is the call I want, if possible
println!("{:?}", A::<DummyType>::get_val());
}
То, что вы реализовали, является связанной функцией, а не методом. Если вашей целью является метод, см. ответ Якуба ниже.
Я ищу связанную функцию, как упомянуто @BallpointBen, чтобы эллидировать турбофиша. В текущей настройке мне может потребоваться создать один или несколько фиктивных типов, чтобы делать то, что я хочу, что я не нахожу особенно чистым.
Чего вам, вероятно, не хватает, так это приемника метода.
pub struct A<T> {
pub field: usize,
pub something: T,
}
pub trait Getter {
type Output;
fn get(&self) -> Self::Output;
}
impl<T> Getter for A<T> {
type Output = usize;
fn get(&self) -> Self::Output {
self.field
}
}
fn main() {
let a = A { field: 10, something: 3.0 };
assert_eq!(a.get(), 10);
}
Тут можно вернуть состояние A
и не просто константу.
Я пробовал с приемником, прежде чем публиковать вопрос, и это действительно работает (извините, что не упомянул об этом). Моя цель состоит в том, чтобы он вызывался без приемника, другими словами, чтобы обойти оператора турбофиша.
Во-первых, ваш дизайн выглядит неправильно. Если тип является универсальным, что означает наличие неуниверсального метода?
В любом случае, вы можете использовать тип сторожевого (и вам не нужен трейт для этого, я действительно не понимаю, почему вы поставили его на первое место):
impl A<()> {
fn get_val() -> i32 {
2
}
}
Компилятор автоматически определяет T
как ()
, когда вы вызываете A::get_val()
.
Хорошо, я попробовал это, и с ржавчиной, похоже, все в порядке:
pub trait Get {
type Output;
fn get() -> Self::Output;
}
pub struct A<T>(T);
impl Get for A<()> {
type Output = usize;
fn get() -> Self::Output {
2
}
}
fn main() {
println!("{}", A::get());
}
()
— лучший выбор, так как вы хотите показать, что параметр здесь не важен для нас, но также не объявлять тип только для этого.
Это кажется странной проблемой. Действительно ли цель состоит в том, чтобы ускользнуть от турбофиша, или есть что-то более глубокое?