Заставить функции создавать экземпляр своего универсального параметра

Что было бы эквивалентно следующей программе C++ в rust?

#include <iostream>
#include <vector>

template <typename T>
T stuff() {
    return T();
}
int main() {
    std::vector<int> vec = stuff<std::vector<int>>();
    vec.push_back(1);
    for (auto &&i : vec) {
        std::cout << i << std::endl;
    }
}

Я пробовал следующее:

trait Newable{
    fn new() -> Self;
}
fn stuff<T: Newable>() -> T {
    T::new()
}

Я попытался использовать новый тип для этого -

struct NwVec<T>{
    vec: Vec<T>
}
impl<T> Newable<T> for NwVec<T>{
    fn new() -> Self {
        NwVec { vec: Vec::new() }
    }
}

и использовал его так:

fn main() {
    let x: NwVec<i32> = stuff::<NwVec<i32>>();
}

но я получаю

error[E0277]: the trait bound `NwVec<i32>: Newable<NwVec<i32>>` is not satisfied
  --> src\main.rs:2:25
   |
2  |     let x: NwVec<i32> = stuff();
   |                         ^^^^^ the trait `Newable<NwVec<i32>>` is not implemented for `NwVec<i32>`
   |
   = help: the following implementations were found:
             <NwVec<T> as Newable<T>>
note: required by a bound in `stuff`

Есть ли способ добиться того, чего достигает программа C++?

P.S.: Я новичок в ржавчине, мне очень жаль, если решение этой проблемы тривиально.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
69
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Возможно, произошла путаница, когда вы ввели код, который, как вы говорите, дал вам предоставленную вами ошибку, потому что тот же самый код не привел к этой конкретной ошибке, когда я попробовал его.

В любом случае, ты был близок. Рассмотрим этот код:

trait Newable {
    fn new() -> Self;
}

fn stuff<T: Newable>() -> T {
    T::new()
}

#[derive(Debug)]
struct NwVec<T> {
    vec: Vec<T>
}

impl<T> Newable for NwVec<T> {
    fn new() -> Self {
        NwVec { vec: Vec::new() }
    }
}

fn main() {
    let x: NwVec<i32> = stuff::<NwVec<i32>>();
    
    println!("{x:?}");
}

Детская площадка

Все, что я изменил, это:

  • Добавлено #[derive(Debug)] к NwVec<T>, чтобы можно было распечатать
  • Я удалил параметр типа <T> на Newable<T> из вашего оригинала impl<T> Newable<T> for NwVec<T>. Это связано с тем, что сама черта Newable, как указано в вашем посте, не является общей, поэтому она не принимает параметр типа.

Я предполагаю, что это что-то вроде обучающего упражнения, но, если вам интересно, вас может заинтересовать std::default::Default, который является чертой, несколько похожей на ваш Newable в том, что реализации обеспечивают простой и последовательный способ создать версию чего-то «по умолчанию». . Vec сам по себе является реализатором, поэтому вы можете вызвать, например. Default::default() или Vec::default() везде, где ожидается Vec<T>. Проверьте эта детская площадка.

да, это должно быть просто то, что мне было любопытно, так как я слышал, что у ржавчины нет стирания шрифта, в любом случае, спасибо.

yaxley peaks 06.05.2022 01:45

@yaxleypeaks В Rust есть стирание шрифта в виде dyn Trait.

Chayim Friedman 06.05.2022 01:59

@ChayimFriedman, мой плохой, я должен был быть более конкретным. В rust нет стирания типов, когда не используются трейт-объекты.

yaxley peaks 06.05.2022 02:01

@yaxleypeaks Но как это связано здесь? Кроме того, это все равно, что сказать, что C++ не поддерживает стирание типов, если не использует наследование. Верно, но бессмысленно.

Chayim Friedman 06.05.2022 02:23

В дополнение к отличному ответу @JorgeIsraelPeña, если вы настаиваете на Newable, вам не нужен новый тип. Вы можете реализовать трейт для типа, пока либо трейт или тип принадлежит вам (ну, фактические правила таковы: немного сложнее). Это означает, что вы можете реализовать Newable непосредственно для Vec:

impl<T> Newable for Vec<T> {
    fn new() -> Self {
        Vec::new()
    }
}

fn main() {
    let x = stuff::<Vec<i32>>();

    println!("{x:?}");
}

Детская площадка.

Нет, я вовсе не настаиваю на Newable. что было бы кратчайшей реализацией этого

yaxley peaks 06.05.2022 01:45

@yaxleypeaks Используя Default.

Chayim Friedman 06.05.2022 01:58

Другие вопросы по теме