关于
Function passed as template argument,Ben Supnik提供的社区wiki答案讨论了内联实例化函数模板的问题.
在那个答案是以下代码:
template<typename OP> int do_op(int a,int b,OP op) { return op(a,b,); } int add(int a,b) { return a + b; } int (* func_ptr)(int,int) = add; int c = do_op(4,5,func_ptr);
答案继续这样说(关于最后一行,实例化函数模板do_op):
clearly this is not getting inlined.
我的问题是:为什么很明显这不是内联的?
解决方法
他所说的(我认为)是add函数没有内联.换句话说,编译器可能会像这样内联do_op:
int c = func_ptr(4,5);
但它也不会像这样添加内联:
int c = 4 + 5;
但是,在这个简单的例子中他可能是错的.
通常,当您通过指针调用函数时,编译器无法(在编译时)知道您将调用哪个函数,因此它无法内联函数.例:
void f1() { ... } void f2() { ... } void callThroughPointer() { int i = arc4random_uniform(2); void (*f)() = i ? f2 : f1; f(); }
这里,编译器无法知道callThroughPointer是否会调用f1或f2,因此无法在callThroughPointer中内联f1或f2.
但是,如果编译器可以在编译时证明将调用哪个函数,则允许内联函数.例:
void f1() { ... } void f2() { ... } void callThroughPointer2() { int i = arc4random_uniform(2); void (*f)() = i ? f2 : f1; f = f1; f(); }
这里,编译器可以证明f将始终为f1,因此允许将f1内联到callThroughPointer2中. (这并不意味着它会内联f1 …)
类似地,在您在帖子中引用的示例中,编译器可以证明func_ptr总是在对do_op的调用中添加,因此允许内联添加. (这并不意味着它会内联添加……)