Можно ли объявить связанный тип, который будет представлять признак?

Можно ли объявить связанный тип, который будет представлять признак? Если нет, что я могу сделать вместо этого? Пытаюсь сделать:

trait Foo {
    /// A trait representing all types that can be returned from baz()
    type ReturnType;
    fn baz(&self) -> Self::ReturnType;
}

Самая большая проблема, с которой я сталкиваюсь, связана с чертой Sized, потому что мне нужна функция, которая возвращает вектор элементов типа, реализующего ReturnType:

trait Foo {
    type ReturnType;
    // option 1
    fn bar(&self) -> Vec<Self::ReturnType>;
    // option 2
    fn bar<T: Self::ReturnType>(&self) -> Vec<T>;
}

Проблема с вариантом 1 заключается в том, что ReturnType не будет иметь размер, потому что это признак, а проблема с вариантом 2 заключается в том, что компилятор не распознает связанный тип как признак: failed to resolve. Use of undeclared type or module 'Self' и use of undeclared trait name 'Self::ReturnType' (что заставляет меня думать, что связанные типы могут не указываю черты)

РЕДАКТИРОВАТЬ: пример того, что я пытаюсь сделать

/// Represents all types that store byte-data instead of the actual
/// element
trait BufferedVec {
    /// the trait representing types that can be converted from the byte-data
    type FromBuffer;
    /// return the data at the given index, converted into a given type
    fn get<T: Self::FromBuffer>(&self, index: usize) -> T;
}

Реализация пользователя может быть

/// An implementation of a BufferedVec
struct MyBufferedVec<'a> {
    data: &'a [Option<Vec<u8>>]
}
impl<'a> BufferedVec for MyBufferedVec<'a> {
    type FromBuffer = MyFromTrait;
    fn get<T: MyFromTrait>(&self, index: usize) -> T {
        <T as MyFromTrait>::convert(self.data[index].as_ref())
    }
}

trait MyFromTrait {
    fn convert(val: Option<&[u8]>) -> Self;
}
impl MyFromTrait for i32 {
    fn convert(val: Option<&[u8]>) -> i32 {
        match val {
             Some(ref bytes) => bytes[0] as i32,
             None            => 0
        }
    }
}
impl MyFromTrait for String {
    fn convert(val: Option<&[u8]>) -> String {
        match val {
             Some(ref bytes) => String::from_utf8(bytes),
             None            => "".to_string()
        }
    }
}

person brandonchinn178    schedule 29.07.2015    source источник


Ответы (1)


Связанные типы не могут указывать черты. В Rust нигде нельзя указывать трейты. Вы можете потребовать, чтобы общий аргумент (или связанный тип) реализовывал признак.

trait Foo {
    type ReturnType: Clone;
}

Таким образом, любые разработчики Foo должны убедиться, что их выбор ReturnType также реализует Clone.

impl Foo for Bar {
    type ReturnType: i32;
}
person oli_obk    schedule 29.07.2015
comment
Верно; я понял, как много - person brandonchinn178; 29.07.2015
comment
какой у вас вариант использования? Есть большая вероятность, что в Rust есть решение вашей реальной проблемы. MCVE, который показывает код, использующий ваши черты и функции-члены, очень поможет. - person oli_obk; 29.07.2015
comment
Я пытаюсь создать API. По сути, я создаю трейты, которые пользователь должен реализовать, чтобы соответствовать моему API. Проблема в том, что я хочу, чтобы одна из функций возвращала что-то, что реализует черту, определяемую пользователем. - person brandonchinn178; 29.07.2015
comment
но так как вы все равно не можете использовать эту черту, поскольку вы ничего о ней не знаете, вы также можете разрешить пользователю передавать любой тип. - person oli_obk; 29.07.2015
comment
ах ... дженерики вместо связанных типов. имеет смысл. Благодарность! - person brandonchinn178; 29.07.2015
comment
однако я хочу, чтобы функция возвращала определенную пользователем черту. То есть, я хочу, чтобы мой API позволял пользователю делать fn foo<T: MyTrait>() -> T. Есть ли способ написать черту, чтобы я мог сказать, что реализует эту функцию, но универсальный реализует черту, которую вы предоставляете? - person brandonchinn178; 30.07.2015
comment
Мне серьезно нужен, поэтому посмотрите код (который явно не компилируется), который показывает, какое поведение вы хотите (включая код, который использует ваши типы и черты и реализует пример типа и черты вашего гипотетического пользователя) - person oli_obk; 30.07.2015