Implement Into for enum CallbackWrapper (closure/simple fn)

    struct Ctx;

    enum Callback {
        Fn(fn(&mut Ctx)),
        Boxed(Box<dyn FnOnce(&mut Ctx)>),
    }

    fn normal_fn(_: &mut Ctx) {}
    let closure_no_capture = |_: &mut Ctx| {};
    let closure_with_capture = {
        let data = vec![];
        move |_: &mut Ctx| drop(data)
    };

    // is it possible to write `impl From` for this?
    fn with_cb(cb: impl Into<Callback>) {}

    with_cb(normal_fn);
    with_cb(closure_no_capture);
    with_cb(closure_with_capture);

This is a wall of code. Do you have a question?

The question is in the comment. I did the following, but because of conflicting implementations I couldn't add another impl that makes use of the Fn variant.

        impl<F: FnOnce(&mut Ctx) + 'static> From<F> for Callback {
            fn from(f: F) -> Self {
                Callback::Boxed(Box::new(f))
            }
        }

Well that shows that the design is flawed. There's no need for the enum whatsoever. Function pointers implement Fn*() traits by themselves.

OP should simply be using Box<dyn FnMut(...)> for storing the function. (For fn items and non-capturing closures, the Self type will be zero-sized, so the Box won't allocate, there won't be overhead.)

4 Likes

Thanks alot.

more info about when Box allocates

Because closure_with_capture only implements FnOnce, I wasn't able to use FnMut.

I'm guessing the question is about how to avoid boxing when passing a regular fn, and you answered that.

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.