Что было бы эквивалентно следующей программе 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.: Я новичок в ржавчине, мне очень жаль, если решение этой проблемы тривиально.
Возможно, произошла путаница, когда вы ввели код, который, как вы говорите, дал вам предоставленную вами ошибку, потому что тот же самый код не привел к этой конкретной ошибке, когда я попробовал его.
В любом случае, ты был близок. Рассмотрим этот код:
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>
. Проверьте эта детская площадка.
@yaxleypeaks В Rust есть стирание шрифта в виде dyn Trait
.
@ChayimFriedman, мой плохой, я должен был быть более конкретным. В rust нет стирания типов, когда не используются трейт-объекты.
@yaxleypeaks Но как это связано здесь? Кроме того, это все равно, что сказать, что C++ не поддерживает стирание типов, если не использует наследование. Верно, но бессмысленно.
В дополнение к отличному ответу @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. что было бы кратчайшей реализацией этого
@yaxleypeaks Используя Default
.
да, это должно быть просто то, что мне было любопытно, так как я слышал, что у ржавчины нет стирания шрифта, в любом случае, спасибо.