I've been wondering is there any way to get pointer of function with unspecified arguments and output types (unspecification of output type isn't as necessary as arguments). For example, in C++ when you are spawning new thread you pass function pointer without any specification.
As I see it can solved with trait that would represent fn
in the same way as std::marker::Tuple
represents Tuple
object.
Example:
struct Cont <F: FN_TRAIT> {
func: F,
}
impl<F: FN_TRAIT> Cont <F> {
fn new(func: F) -> Self {
Self { func: func }
}
fn start(&self, args: dyn std::marker::Tuple) {
self.func.call(args);
}
}
fn temp(a: i32, b: i32) {
println!("{}", a + b);
}
fn main() {
let a = Cont::new(temp);
a.start((0,1));
}
I tried to find the way to represent fn
with trait in the struct and then call it with std::marker::Tuple as arguments.
You can do it with generics mostly the same as C++ does it:
struct Cont<Args, F> {
args: Args,
fun: F,
}
impl<Args, F> Cont<Args, F> {
fn new (fun: F, args: Args) -> Self {
Cont { args, fun, }
}
}
impl<A, R, F: FnOnce (A) -> R> Cont<(A,), F> {
fn call (self) -> R {
(self.fun) (self.args.0)
}
}
impl<A0, A1, R, F: FnOnce (A0, A1) -> R> Cont<(A0, A1), F> {
fn call (self) -> R {
(self.fun) (self.args.0, self.args.1)
}
}
fn main() {
let c1 = Cont::new (|x| 2*x, (0,));
let c2 = Cont::new (|x, y| x+y, (2, 3));
println!("{} {}", c1.call(), c2.call());
}
Except that you need to add an implementation for each possible number of arguments (this can probably be simplified with a macro).