如何实现一个函数来调用任意(任意)函数及其(任意)参数?

时间:2014-08-06 10:00:03

标签: c++ reflection functional-programming polymorphism

我想要以下内容:

void foo( 
    /* something representing a function f */,
    /* arguments a1, a2, etc. in some form */ ) 
{
    /* magic - invoke f(a1, a2, etc.)*/
}

/* ... */

void bar(float f, char* s);
void baz(int i);
/* etc. */

int main() {
    /* ... */
    foo(bar, SomeKindOfTransformationOrNoneAtAll(f, s));
    foo(baz, SomeKindOfTransformationOrNoneAtAll(i));
    /* etc. */
}

我可以实施foo()吗?也就是说,我可以编写一个函数,它接受一个任意的其他函数,一堆参数(varargs,或vector,或者,或者你有什么),并使用传递的参数调用传递的函数?

如果可以的话,是否有一个便于它的图书馆?还是一些常见的习语?

注意:

  • 我不想将参数绑定到foo()之外的函数,而是绑定在其中。因此,foo()必须不仅仅需要一个函数* / std :: function / etc.参数。

3 个答案:

答案 0 :(得分:3)

Variadic模板确实可以做到这一点。

template<typename T, typename... Args> void foo(T func, Args&&... args) {
    func(std::forward<Args>(args)...);
}

然后直接将参数传递给foo。这称为完美转发。然而,对于lambdas来说,将它们绑定在那里真的更惯用。

template<typename T> void foo(T func) {
    func();
}    
int main() {
    foo([] { baz(param1, param2); });
}

如果它们不是常数,你可以捕获它们。这是一个很好的选择,因为如果需要,您可以轻松地将模板转换为非模板,并且可以避免参数生存期与否的问题,因为lambda用户可以捕获它们所需的。您可以采用这种方式而不是仅使用一个对象,因为可变参数包只能出现一次。最后,在使用命名函数时,你不需要选择单个函数指针。

答案 1 :(得分:0)

您似乎在寻找std::bind

所以,比如:

void foo(std::function<void()> fun) {
    fun();
}

foo(std::bind(bar, 0.1f, "abc"));
foo(std::bind(baz, 42));

答案 2 :(得分:0)

如果我理解正确,你想在调用者的网站上决定应该调用哪个函数。

最简单的解决方案是使用带有std :: function的lambda:

void foo(std::function<void(void)> f) { // std::function has strong magic
    // whatever you want here
    f();
    // whatever you want here
}

/* ... */

void bar(float f, char* s);
void baz(int i);
/* etc. */

int main() {
    foo( [f, s]() { bar(f, s); } );
    foo( [&i]() { baz(i) } );
    /* etc. */
}