まず、テンプレートラッパーのインスタンス化の速度は、ほぼ完全にオプティマイザーに翻弄されます。
そうは言っても、特に関数パラメーターの呼び出しをチェックするために、サンプルを私が考えることができる最も基本的なコードに減らしました。読み進めることはできますが、まったく同じように呼び出されることがわかります。ある宣言と別の宣言には利点がありません。さらに、あなたが省略したものを含めました(reference-decl)
#include <cstdio>
int hello(int x)
{
return x;
}
template<typename Type>
void apply1(Type x, Type (f)(Type))
{
f(x);
}
template<typename Type>
void apply2(Type x, Type (*f)(Type))
{
f(x);
}
template<typename Type>
void apply3(Type x, Type (&f)(Type))
{
f(x);
}
int main(int argc, char *argv[])
{
apply1(1,hello);
apply2(2,hello);
apply3(3,hello);
return 0;
}
控除から生成される実際のasmは次のとおりです。
apply1
__Z6apply1IiEvT_PFS0_S0_E:
Leh_func_begin2:
pushq %rbp
Ltmp2:
movq %rsp, %rbp
Ltmp3:
subq $16, %rsp
Ltmp4:
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
movq -16(%rbp), %rax
movl -4(%rbp), %ecx
movl %ecx, %edi
callq *%rax
addq $16, %rsp
popq %rbp
ret
Leh_func_end2:
apply2
__Z6apply2IiEvT_PFS0_S0_E:
Leh_func_begin3:
pushq %rbp
Ltmp5:
movq %rsp, %rbp
Ltmp6:
subq $16, %rsp
Ltmp7:
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
movq -16(%rbp), %rax
movl -4(%rbp), %ecx
movl %ecx, %edi
callq *%rax
addq $16, %rsp
popq %rbp
ret
Leh_func_end3:
apply3
__Z6apply3IiEvT_RFS0_S0_E:
Leh_func_begin4:
pushq %rbp
Ltmp8:
movq %rsp, %rbp
Ltmp9:
subq $16, %rsp
Ltmp10:
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
movq -16(%rbp), %rax
movl -4(%rbp), %ecx
movl %ecx, %edi
callq *%rax
addq $16, %rsp
popq %rbp
ret
Leh_func_end4:
それらは同一です(私が思ったように)。私が何でも見ることができるという違いはありません。
注:コンパイラーがこれらの宣言を名前マングリング検査でどのように見たかについて言及する価値があります。
apply1: __Z6apply1IiEvT_PFS0_S0_E
apply2: __Z6apply2IiEvT_PFS0_S0_E
apply3: __Z6apply3IiEvT_RFS0_S0_E