Is there any way to save pointer of any function in the struct?

huangapple go评论62阅读模式
英文:

Is there any way to save pointer of any function in the struct?

问题

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 be 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.

英文:

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 &lt;F: FN_TRAIT&gt; {
    func: F,
}

impl&lt;F: FN_TRAIT&gt; Cont &lt;F&gt; {
    fn new(func: F) -&gt; Self {
        Self { func: func }
    }

    fn start(&amp;self, args: dyn std::marker::Tuple) {
        self.func.call(args);
    }
}

fn temp(a: i32, b: i32) {
    println!(&quot;{}&quot;, 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.

答案1

得分: 0

你可以使用泛型来完成大部分与C++类似的操作:

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());
}

(注意:我只提供了代码的翻译部分,没有其他内容。)

英文:

You can do it with generics mostly the same as C++ does it:

struct Cont&lt;Args, F&gt; {
    args: Args,
    fun: F,
}

impl&lt;Args, F&gt; Cont&lt;Args, F&gt; {
    fn new (fun: F, args: Args) -&gt; Self {
        Cont { args, fun, }
    }
}

impl&lt;A, R, F: FnOnce (A) -&gt; R&gt; Cont&lt;(A,), F&gt; {
    fn call (self) -&gt; R {
        (self.fun) (self.args.0)
    }
}

impl&lt;A0, A1, R, F: FnOnce (A0, A1) -&gt; R&gt; Cont&lt;(A0, A1), F&gt; {
    fn call (self) -&gt; 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!(&quot;{} {}&quot;, c1.call(), c2.call());
}

Playground

Except that you need to add an implementation for each possible number of arguments (this can probably be simplified with a macro).

huangapple
  • 本文由 发表于 2023年5月17日 13:19:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76268774.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定