Как я могу скопировать общий срез, чтобы иметь срез в штучной упаковке? - PullRequest
1 голос
/ 30 мая 2019

У меня есть контейнер:

pub struct Foo<T> {
    pub data: Box<[T]>,
}

Я хотел бы, чтобы метод инициализировал новый из существующего среза:

impl<T> Foo<T> {
    fn from_slice(slice: &[T]) -> Foo<T> {
        Foo {
            data: Box::new(/* something here */),
        }
    }
}

Я хотел бы создать Foo экземпляр из любого среза, взятый из динамического вектора или статической строки.

Полагаю, есть причина, по которой vec! является макросом, но есть ли способ избежать его написания?Я думаю, я мог бы сделать slice.to_vec().into_boxed_slice(), но кажется неправильным создавать Vec в качестве прокси для клона ...

Я не использую Vec в своей структуре, потому чтоdata не должен изменяться в размере в течение срока службы моего контейнера.Было неправильно использовать Vec, но я могу ошибаться.

1 Ответ

4 голосов
/ 30 мая 2019

Если ваш срез содержит Copy типов, вы можете использовать From / Into для выполнения построения:

pub struct Foo<T> {
    pub data: Box<[T]>,
}

impl<T> Foo<T> {
    fn from_slice(slice: &[T]) -> Foo<T>
    where
        T: Copy,
    {
        Foo { data: slice.into() }
    }
}

Если ваши данные Clone, то вы можете использовать to_vec + into_boxed_slice:

impl<T> Foo<T> {
    fn from_slice(slice: &[T]) -> Foo<T>
    where
        T: Clone,
    {
        Foo { data: slice.to_vec().into_boxed_slice() }
    }
}

представляется неправильным создание Vec в качестве прокси для клона

You arenне клонируемся здесь.Когда вы клонируете тип T, вы получаете тип T обратно.Вы начинаете с &[T] и хотите получить Box<[T]>, а не [T] (которого у вас не может быть).

Создание коробочного среза через Vec означает, что вы временно берете 3 целых числа машинного размера вместо 2;вряд ли это будет проблемой производительности по сравнению с объемом выполненного выделения.

Я согласен с ответом starblue , что сохранение Vec<T>, вероятно, проще для большинства случаев, но я допускаючто в некоторых случаях полезно иметь коробочный срез.

См. также:

Iпредположим, что есть причина, по которой vec! является макросом

Публичная реализация vec! является общедоступной:

macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        <[_]>::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

Это действительно только макросдля удобства синтаксиса (и потому что он использует ключевое слово unstable box);он принимает аргументы, создает массив, упаковывает его, приводит к преобразованию в штучный фрагмент, а затем преобразует в Vec.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...