Idiomatic way to write a factory method for generic type with "hidden" specialised type

Hello everyone.

Can you please enlighten me about idiomatic way to write factory method with generic type, where single concrete specialisation is hidden inside method.

Given this generic struct:

struct Container<T>
where
    T: PartialOrd,
{
    smth: T,
}

Tried to naively write factory method:

example 1:

impl<T> Container<T>
where
    T: PartialOrd,
{
   fn new_invalid() -> Self {
       Self {
            smth: 123u8,
       }
    }
}

got a compile error:

   |
8  | impl<T> Container<T>
   |      - expected this type parameter
...
15 |             smth: 123u8,
   |                   ^^^^^ expected type parameter `T`, found `u8`
   |
   = note: expected type parameter `T`
                        found type `u8

If I understand correctly, compiler guards from the situation when (if it was legit) one can get a type mismatch, trying to specify type on callee side(u8 vs i32):

Container::<i32>::new_explicit();

and that ofc could lead to an invalid call.
And to forbid such scenarios generic return type (Self or Container) is not allowed to be used when specialised type, that "narrows" it, returned.

On the other hand, this realisation compiles ok:

example 2:

impl<T> Container<T>
where
    T: PartialOrd,
{
    
    // this works. but is this idiomatic way?
    // should one use explicit signature, thus specifying specific narrow type?
    fn new_explicit() -> Container<u8> {
        Container {
            smth: 123u8,
        }
}

Playground link

The question is:
Is it(example 2) idiomatic way to write factories with single specific narrowed generic types in return position?

I realise that stdlib must be full of examples, but can't find anything.

PS
I'd like to mention that I'm interested in NON dynamic situation only, in other words, dynamic scenarios like:

if ...
        Container {
            smth: 123u8,
        }
else ...
        Container {
            smth: 123u32,
        }

is not the problem, I understand that it's a whole different beast. Just a straight scenario, with only one type, like in example.

Thanks in advance

Put the constructor in an impl block that suits it:

impl Container<u8> {
   fn new() -> Self {
       Self {
            smth: 123u8,
       }
    }
}
1 Like

Thank you, that even more clean from the point of caller!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.