1

I have this generic type:

pub struct MyContainer<T, S> {
    array: Vec<T>,
    get_size: S,
    size: u32,
}

impl<T: Default, S> MyContainer<T, S>
where
    S: Fn(&T) -> u32,
{
    pub fn new(size: u32, get_size: S) -> MyContainer<T, S> {
        let array = Vec::with_capacity(size as usize);
        MyContainer {
            array,
            get_size,
            size,
        }
    }
}

I can easily create a container using compiler deduction magic:

pub fn get_size_func(h: &House) -> u32 {
    h.num_rooms
}
let container = MyContainer::new(6, get_size);

However, I'm hitting an issue when I try to instantiate my generic type in another struct:

pub struct City {
    suburbs: MyContainer<House, fn(&House) -> u32>,
}

impl City {
    pub fn new(num_houses: u32) -> City {
        let container = MyContainer::new(num_houses, get_size_func);
        City { suburbs: container }
    }
}

I get

error[E0308]: mismatched types
  --> src/lib.rs:44:25
   |
44 |         City { suburbs: container }
   |                         ^^^^^^^^^ expected fn pointer, found fn item
   |
   = note: expected type `MyContainer<_, for<'r> fn(&'r House) -> u32>`
              found type `MyContainer<_, for<'r> fn(&'r House) -> u32 {get_size_func}>`

Here's the Rust playground that reproduces the problem

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
NutellaFan
  • 85
  • 8
  • Your question may be answered by the answers of [Right way to have Function pointers in struct](https://stackoverflow.com/questions/37370120/right-way-to-have-function-pointers-in-struct) / [How do I call a function through a member variable?](https://stackoverflow.com/q/27994509/155423). If you agree, we can mark this question as already answered. – Shepmaster Nov 02 '18 at 02:26
  • Ah, I need fn instead of Fn. But I'm now hitting a case where when I try to call the City new function. Thanks for the other tips BTW, I'll try to create a new Rust playground should I have another question. – NutellaFan Nov 02 '18 at 03:32

1 Answers1

1

There's two answers to this question:

  1. Specifying the type parameters when creating the the container. I don't know why that works, but it does:

    let container = MyContainer::<House, fn(&House) -> u32>::new(num_houses, get_size_func);
    
  2. You can also define a generic function that calls a generic trait for an added kick. For example:

     let container = MyContainer::<House, fn(&House) -> u32>::new(num_houses, get_size_func2::<House>);
    

    get_size_func2 would be a trait bound generic function.

Here's the full playground. For both solutions, type parameters are required and not deduced in the City::new function.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
NutellaFan
  • 85
  • 8
  • [What is a function signature and type?](https://stackoverflow.com/questions/42157511/what-is-a-function-signature-and-type) — every function has a unique type that is *not* the function pointer type. – Shepmaster Nov 03 '18 at 23:46
  • @Shepmaster can you hint as to why this is? It seems that to have generic functions (e.g. a table of binary operators that take two u64s and return another u64) requires function signatures to be repeated with an `as fn(x) -> y` cast. What's the benefit? – Desty Feb 17 '20 at 20:58
  • @Desty [why do you say that](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=668cea6d3b1249d513d46d0571e1dbb4)? – Shepmaster Feb 18 '20 at 00:08
  • @Shepmaster just wondering if you knew the reason that the "every function has a unique type" feature was added to Rust. Like, what problem that solves. I just discovered it while trying to apply a series of functions to some input, and was surprised that it was not possible without casting them to a more generic function pointer with `as`. – Desty Feb 19 '20 at 00:00
  • @Shepmaster oh just noticed your example in the Playground where that isn't necessary. Now I'm more confused than ever! :D – Desty Feb 19 '20 at 00:01