我们如何将任意函数传递给另一个函数

时间:2013-02-06 01:10:32

标签: c++

我有一个问题继续发布Function passed as template argument。在提供的代码中:

#include <iostream>

void add1(int &v)
{
  v+=1;
}

void add2(int &v)
{
  v+=2;
}

template <void (*T)(int &)>
void doOperation()
{
  int temp=0;
  T(temp);
  std::cout << "Result is " << temp << std::endl;
}

int main()
{
  doOperation<add1>();
  doOperation<add2>();
}

具有不同参数集布局的第三个函数怎么样,例如

double add3(double v1, double v2)
{
return v1+v2;
}

如果根本无法使用模板实现这一点,我们如何将任意函数传递给另一个函数?我们如何处理具有各种可能性的参数集?我知道python可以通过传递一个元组(kwargs **)来实现,但不确定C / C ++。

2 个答案:

答案 0 :(得分:1)

传递要调用的泛型函数的一种形式是可调用的模板化类型:

#include <functional>
#include <iostream>

template<typename F>
void callFoo(F f) {
   f();
}

int main() {
   callFoo(std::bind([](int a, int b) {std::cout << a << ' ' << b;}, 5, 6));
}

callFoo采用可调用类型F并调用它。例如,围绕此调用,您可以执行计时器工作以计时功能。在main中,它被一个lambda调用,该lambda有两个参数,并且这些参数的值被绑定到它。然后callFoo可以在不存储参数的情况下调用它。这与使用std::function<void()>类型的参数非常相似。

但是,如果您不想使用std::bind,则可以通过一些更改单独传递参数:

template<typename F, typename... Args>
void callFoo(F f, Args... args) { //ignoring perfect forwarding
    f(args...);
}

int main() {
    callFoo(/*lambda*/, 5, 6);
}

在这些情况下,传递void函数是有意义的。实际上,返回值可以用作参数并通过std::ref传递。如果您计划返回函数返回的内容,则必须处理返回类型为void的特殊情况,因为您无法分配给void变量并返回该变量。此时,您可以更轻松地将您引导至previous question。我的用例结果证明是没有实际意义,但该解决方案非常适合其他用途。

答案 1 :(得分:0)

这可能会让你更接近你想要的东西:

#include <iostream>

void add1(int &v)
{
    v+=1;
}

double add2(double v1, double v2)
{
    return v1 + v2;
}

// 1 param version
template< class aRetType, class tP1 >
aRetType doOperation( aRetType (*aFunction)( tP1 aP1 ), tP1 valP1  )
{
    return aFunction( valP1 );
}

// 2 param version
template< class aRetType, class tP1, class tP2 >
aRetType doOperation( aRetType (*aFunction)( tP1 aP1, tP2 aP2 ), tP1 valP1, tP2 valP2 )
{
    return aFunction( valP1, valP2 );
}

// 3 param version and up is not given, but you get the trick.

int main()
{
    int iTemp = 8;
    doOperation< void, int& >( add1, iTemp );
    std::cout << "Result is " << iTemp << std::endl;

    double iResult;
    iResult = doOperation< double, double, double >( add2, 2.2, 8.8);
    std::cout << "Result is " << iResult << std::endl;
}