作为模板参数传递的C ++函数与参数 [英] C++ Function passed as Template Argument vs Parameter
问题描述
在C ++中,有两种方法可以将函数传递给另一个看起来相当的函数。
In C++, there are two ways of passing a function into another function that seem equivalent.
#include <iostream>
int add1(int i){ return i+1; }
int add2(int i){ return i+2; }
template <int (*T)(int) >
void doTemplate(int i){
std::cout << "Do Template: " << T(i) << "\n";
}
void doParam(int i, int (*f)(int)){
std::cout << "Do Param: " << f(i) << "\n";
}
int main(){
doTemplate<add1>(0);
doTemplate<add2>(0);
doParam(0, add1);
doParam(0, add2);
}
doTemplate接受函数作为模板参数,而doParam接受函数
doTemplate accepts a function as a template argument, whereas doParam accepts it as a function pointer, and they both seem to give the same result.
使用每个方法之间的折衷是什么?
What are the trade-offs between using each method?
推荐答案
基于模板的版本允许编译器内联调用,因为函数的地址在编译时是已知的。显然,缺点是函数的地址在编译时是已知的(因为你使用它作为模板参数),有时这可能是不可能的。
The template-based version allows the compiler to inline the call, because the address of the function is known at compile-time. Obviously, the disadvantage is that the address of the function has to be known at compile-time (since you are using it as a template argument), and sometimes this may not be possible.
这就带来了第二种情况,其中函数指针只能在运行时确定,因此编译器不可能执行内联,但是给你灵活性在运行时确定要调用的函数:
That brings us to the second case, where the function pointer may be determined only at run-time, thus making it impossible for the compiler to perform the inlining, but giving you the flexibility of determining at run-time the function to be called:
bool runtimeBooleanExpr = /* ... */;
doParam(0, runtimeBooleanExpr ? add1 : add2);
但请注意,还有第三种方式:
Notice, however, that there is a third way:
template<typename F>
void doParam(int i, F f){
std::cout << "Do Param: " << f(i) << "\n";
}
这给你更多的灵活性,并且仍然具有在编译时知道的优势什么函数被调用:
Which gives you more flexibility and still has the advantage of knowing at compile-time what function is going to be called:
doParam(0, add1);
doParam(0, add2);
还允许传递任何可调用对象而不是函数指针:
And it also allows passing any callable object instead of a function pointer:
doParam(0, my_functor());
int fortyTwo = 42;
doParam(0, [=] (int i) { return i + fortyTwo; /* or whatever... */ }
为了完整起见,还有一种第四种方法,使用 std :: function
:
For completeness, there is also a fourth way, using std::function
:
void doParam(int x, std::function<int(int)> f);
这具有相同的通用性(可以传递任何可调用对象),但也允许您在运行时确定可调用对象 - 最可能的性能损失,因为(再一次)内联对于编译器是不可能的。
Which has the same level of generality (in that you can pass any callable object), but also allows you to determine the callable object at run-time - most likely with a performance penalty, since (once again) inlining becomes impossible for the compiler.
有关最后两个选项的进一步讨论,还见 此问题在StackOverflow上的问答 。
For a further discussion of the last two options, also see this Q&A on StackOverflow.
这篇关于作为模板参数传递的C ++函数与参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!