I have a struct that stores a couple of references to closures
struct FnThing<'a, F: Fn()> {
f: &'a F,
}
I want to implement the Default
trait for FnThing
where f
has default value of a no-op ||{}
function.
Since f
is a reference, I plan to accomplish this by creating a static no-op closure function so that I can set the defualt value as
impl<'a, F: Fn()> Default for FnThing<'a, F> {
fn default() -> Self {
Self { f: &NO_OP }
}
}
static NO_OP: impl Fn = ||{};
rust complains that
`impl Trait` only allowed in function and inherent method return types, not in const types
Fair enough
static NO_OP: dyn Fn() = || {};
Now it complains that
the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time
OK, for unknown size, I should use the heap
static NO_OP: Box<dyn Fn()> = Box::new(|| {});
Now it complains
`(dyn Fn() + Send + 'static)` cannot be shared between threads safely
I don't care about multithreading atm, but it would still be nice if my code was thread safe in case I do in the future. Though I fail understand why this isn't thread safe.
Why not just use a simple function pointer?
static NO_OP: fn() = || {};
impl<'a, F: Fn()> Default for FnThing3<'a, F> {
fn default() -> Self {
Self { f: NO_OP }
}
}
This doesn't work since fn()
and F: Fn()
are different types. Following this answer, I try
fn default() -> Self {
Self {
f: (Box::new(NO_OP) as Box<dyn Fn()>).as_ref(),
}
}
but it still gives me the error
expected `&F`, found `&dyn Fn()`
I'm out of ideas... How do I create a static constant closure?
You're almost there. Your problem right now is that you're trying to get a generic F: impl Fn()
. You can just not write that, since you can't have a default over every generic type. So just impl Default
for the case where F
is just fn()
, like so:
struct FnThing<'a, F: Fn()> {
f: &'a F,
}
static NO_OP: fn() = || {};
impl<'a> Default for FnThing<'a, fn()> {
fn default() -> Self {
FnThing { f: &NO_OP }
}
}
I think this is the what you want. Let me know if it works the way you want!