What would be an equivalent to the following C program in 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;
}
}
I tried the following:
trait Newable{
fn new() -> Self;
}
fn stuff<T: Newable>() -> T {
T::new()
}
I tried using a newtype for this -
struct NwVec<T>{
vec: Vec<T>
}
impl<T> Newable<T> for NwVec<T>{
fn new() -> Self {
NwVec { vec: Vec::new() }
}
}
and used it like so:
fn main() {
let x: NwVec<i32> = stuff::<NwVec<i32>>();
}
but I get a
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`
Is there a way to achieve what the C program achieves?
P.S.: I am rather new to rust, I am really sorry if the solution to this is trivial.
CodePudding user response:
Maybe there was a mixup when you entered the code that you say gave you the error you provided, because that same code did not yield that specific error when I tried it.
Either way, you were close. Consider this code:
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:?}");
}
All I changed was:
- Added
#[derive(Debug)]
toNwVec<T>
so we could print it out - I removed the type parameter
<T>
onNewable<T>
from your originalimpl<T> Newable<T> for NwVec<T>
. This is because theNewable
trait itself, as provided in your post, is not generic, so it takes no type parameter.
I imagine this is something of a learning exercise, but in case you were curious, you may be interested in std::default::Default
which is a trait somewhat similar to your Newable
in that implementations provide a simple and consistent way to create a "default" version of something. Vec
itself is an implementer, so you can call e.g. Default::default()
or Vec::default()
wherever a Vec<T>
is expected. Check this playground.
CodePudding user response:
Adding to the excellent answer by @JorgeIsraelPeña, in case you insist on Newable
, you don't need a newtype. You can implement a trait for a type as long as either the trait or the type are yours (well, the actual rules are a bit more complicated). That means you can implement Newable
directly for Vec
:
impl<T> Newable for Vec<T> {
fn new() -> Self {
Vec::new()
}
}
fn main() {
let x = stuff::<Vec<i32>>();
println!("{x:?}");
}