函数模板
模板的意义:对类型也参数化
int sum1(int a,int b){return a+b;}
double sum2(double a ,double b){return a+b;}

几个概念
函数模板
模板的实例化
模板函数

模板类型参数
模板非类型参数

模板实参推演
模板的特例化
模板函数,模板的特例化,非模板函数的重载关系

点击查看代码
template<typename T,typename E> //定义一个模板参数列表 或者用 class T 也可以
bool compare(T x ){ //compare 是一个函数模板,它目前只是个模板
   cout<<"Template Compare"<<endl;
   return x>y;
}
int main(){
    //函数的调用点,在函数调用点,编译器用用户指定的类型,从原模板实例化一份函数代码出来
    // bool compare<int>(int a,int b){return a>b;}  这个从模板实例化出来的函数 就叫模板函数
    // bool compare<double>(double a, double b){return a>b} 这个从模板实例化出来的函数 就叫模板函数
    //模板函数是编译器根据指定的类型从模板实例化出来 参与编译的函数
    //从用户的角度来看,我们只写了一份模板代码,代码量是变少了,但是对于编译器来说,需要编译的代码没有减少,都需要根据指定的类型实例化出来具体函数
    compare<int>(1,2);//
    compare(100,200);//也可以,编译器会根据实参类型进行推演出 compare<int> 进行模板的实例化.
    //注意如果有compare<int>(1,2); 然后有compare(100,200);
    //编译器不会生成两套同样的 bool compare<int>(int a,int b){return a>b;},因为这个函数是需要在编译期间生成符号表,
    //如果生成两次,会出现在符号表中重名问题
    return 1;
}

示例代码2 不实例话模板 并查看编译后.o文件中的 符号表情况

点击查看代码
#include <iostream>
using namespace std;
template<typename T>
bool compare(T x,T y){
    return x,y;
}
int main(){
    return 1;
}
//编译后查看.o文件中的符号表信息如下 符号表中看不到compare函数的符号
kl@kl-ThinkPad-T580:/data/usershare/code/compile$ objdump -t test1.o
test1.o:     文件格式 elf64-x86-64
SYMBOL TABLE:
0000000000000318 l    d  .interp        0000000000000000              .interp
0000000000000338 l    d  .note.gnu.property     0000000000000000              .note.gnu.property
0000000000000358 l    d  .note.gnu.build-id     0000000000000000              .note.gnu.build-id
000000000000037c l    d  .note.ABI-tag  0000000000000000              .note.ABI-tag
00000000000003a0 l    d  .gnu.hash      0000000000000000              .gnu.hash
00000000000003c8 l    d  .dynsym        0000000000000000              .dynsym
00000000000004a0 l    d  .dynstr        0000000000000000              .dynstr
0000000000000576 l    d  .gnu.version   0000000000000000              .gnu.version
0000000000000588 l    d  .gnu.version_r 0000000000000000              .gnu.version_r
00000000000005c8 l    d  .rela.dyn      0000000000000000              .rela.dyn
00000000000006b8 l    d  .rela.plt      0000000000000000              .rela.plt
0000000000001000 l    d  .init  0000000000000000              .init
0000000000001020 l    d  .plt   0000000000000000              .plt
0000000000001050 l    d  .plt.got       0000000000000000              .plt.got
0000000000001060 l    d  .plt.sec       0000000000000000              .plt.sec
0000000000001080 l    d  .text  0000000000000000              .text
0000000000001258 l    d  .fini  0000000000000000              .fini
0000000000002000 l    d  .rodata        0000000000000000              .rodata
0000000000002008 l    d  .eh_frame_hdr  0000000000000000              .eh_frame_hdr
0000000000002060 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000003d90 l    d  .init_array    0000000000000000              .init_array
0000000000003da0 l    d  .fini_array    0000000000000000              .fini_array
0000000000003da8 l    d  .dynamic       0000000000000000              .dynamic
0000000000003fa8 l    d  .got   0000000000000000              .got
0000000000004000 l    d  .data  0000000000000000              .data
0000000000004010 l    d  .bss   0000000000000000              .bss
0000000000000000 l    d  .comment       0000000000000000              .comment
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000010b0 l     F .text  0000000000000000              deregister_tm_clones
00000000000010e0 l     F .text  0000000000000000              register_tm_clones
0000000000001120 l     F .text  0000000000000000              __do_global_dtors_aux
0000000000004010 l     O .bss   0000000000000001              completed.8059
0000000000003da0 l     O .fini_array    0000000000000000              __do_global_dtors_aux_fini_array_entry
0000000000001160 l     F .text  0000000000000000              frame_dummy
0000000000003d90 l     O .init_array    0000000000000000              __frame_dummy_init_array_entry
0000000000000000 l    df *ABS*  0000000000000000              TemplateTest1.cpp
0000000000002004 l     O .rodata        0000000000000001              _ZStL19piecewise_construct
0000000000004011 l     O .bss   0000000000000001              _ZStL8__ioinit
0000000000001178 l     F .text  000000000000004d              _Z41__static_initialization_and_destruction_0ii
00000000000011c5 l     F .text  0000000000000019              _GLOBAL__sub_I_main
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000021a4 l     O .eh_frame      0000000000000000              __FRAME_END__
0000000000000000 l    df *ABS*  0000000000000000              
0000000000002008 l       .eh_frame_hdr  0000000000000000              __GNU_EH_FRAME_HDR
0000000000001000 l     F .init  0000000000000000              _init
0000000000003da8 l     O .dynamic       0000000000000000              _DYNAMIC
0000000000003da0 l       .init_array    0000000000000000              __init_array_end
0000000000003d90 l       .init_array    0000000000000000              __init_array_start
0000000000003fa8 l     O .got   0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000004010 g       .data  0000000000000000              _edata
0000000000004000  w      .data  0000000000000000              data_start
0000000000002000 g     O .rodata        0000000000000004              _IO_stdin_used
0000000000000000  w    F *UND*  0000000000000000              __cxa_finalize@@GLIBC_2.2.5
0000000000001169 g     F .text  000000000000000f              main
0000000000004008 g     O .data  0000000000000000              .hidden __dso_handle
0000000000001258 g     F .fini  0000000000000000              .hidden _fini
0000000000000000       F *UND*  0000000000000000              __cxa_atexit@@GLIBC_2.2.5
0000000000001080 g     F .text  000000000000002f              _start
0000000000004010 g     O .data  0000000000000000              .hidden __TMC_END__
0000000000004000 g       .data  0000000000000000              __data_start
0000000000004018 g       .bss   0000000000000000              _end
0000000000004010 g       .bss   0000000000000000              __bss_start
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
00000000000011e0 g     F .text  0000000000000065              __libc_csu_init
0000000000000000  w      *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000001250 g     F .text  0000000000000005              __libc_csu_fini
0000000000000000       F *UND*  0000000000000000              __libc_start_main@@GLIBC_2.2.5
0000000000000000  w      *UND*  0000000000000000              __gmon_start__
0000000000000000  w      *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4

示例代码3 实例化模板 并查看编译后.o文件中的 符号表情况

点击查看代码
#include <iostream>
using namespace std;
template<typename T>
bool compare(T x,T y){
    return x,y;
}
int main(){
    bool b=compare<int>(100,200);
    return 1;
}
//编译生成.o文件,查看其中的符号表信息, 在其中找到了 compare函数的符号表
kl@kl-ThinkPad-T580:/data/usershare/code/compile$ objdump -t test1.o
test1.o:     文件格式 elf64-x86-64
SYMBOL TABLE:
0000000000000318 l    d  .interp        0000000000000000              .interp
0000000000000338 l    d  .note.gnu.property     0000000000000000              .note.gnu.property
0000000000000358 l    d  .note.gnu.build-id     0000000000000000              .note.gnu.build-id
000000000000037c l    d  .note.ABI-tag  0000000000000000              .note.ABI-tag
00000000000003a0 l    d  .gnu.hash      0000000000000000              .gnu.hash
00000000000003c8 l    d  .dynsym        0000000000000000              .dynsym
00000000000004a0 l    d  .dynstr        0000000000000000              .dynstr
0000000000000576 l    d  .gnu.version   0000000000000000              .gnu.version
0000000000000588 l    d  .gnu.version_r 0000000000000000              .gnu.version_r
00000000000005c8 l    d  .rela.dyn      0000000000000000              .rela.dyn
00000000000006b8 l    d  .rela.plt      0000000000000000              .rela.plt
0000000000001000 l    d  .init  0000000000000000              .init
0000000000001020 l    d  .plt   0000000000000000              .plt
0000000000001050 l    d  .plt.got       0000000000000000              .plt.got
0000000000001060 l    d  .plt.sec       0000000000000000              .plt.sec
0000000000001080 l    d  .text  0000000000000000              .text
0000000000001288 l    d  .fini  0000000000000000              .fini
0000000000002000 l    d  .rodata        0000000000000000              .rodata
0000000000002008 l    d  .eh_frame_hdr  0000000000000000              .eh_frame_hdr
0000000000002068 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000003d90 l    d  .init_array    0000000000000000              .init_array
0000000000003da0 l    d  .fini_array    0000000000000000              .fini_array
0000000000003da8 l    d  .dynamic       0000000000000000              .dynamic
0000000000003fa8 l    d  .got   0000000000000000              .got
0000000000004000 l    d  .data  0000000000000000              .data
0000000000004010 l    d  .bss   0000000000000000              .bss
0000000000000000 l    d  .comment       0000000000000000              .comment
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000010b0 l     F .text  0000000000000000              deregister_tm_clones
00000000000010e0 l     F .text  0000000000000000              register_tm_clones
0000000000001120 l     F .text  0000000000000000              __do_global_dtors_aux
0000000000004010 l     O .bss   0000000000000001              completed.8059
0000000000003da0 l     O .fini_array    0000000000000000              __do_global_dtors_aux_fini_array_entry
0000000000001160 l     F .text  0000000000000000              frame_dummy
0000000000003d90 l     O .init_array    0000000000000000              __frame_dummy_init_array_entry
0000000000000000 l    df *ABS*  0000000000000000              TemplateTest1.cpp
0000000000002004 l     O .rodata        0000000000000001              _ZStL19piecewise_construct
0000000000004011 l     O .bss   0000000000000001              _ZStL8__ioinit
000000000000118e l     F .text  000000000000004d              _Z41__static_initialization_and_destruction_0ii
00000000000011db l     F .text  0000000000000019              _GLOBAL__sub_I_main
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000021cc l     O .eh_frame      0000000000000000              __FRAME_END__
0000000000000000 l    df *ABS*  0000000000000000              
0000000000002008 l       .eh_frame_hdr  0000000000000000              __GNU_EH_FRAME_HDR
0000000000001000 l     F .init  0000000000000000              _init
0000000000003da8 l     O .dynamic       0000000000000000              _DYNAMIC
0000000000003da0 l       .init_array    0000000000000000              __init_array_end
0000000000003d90 l       .init_array    0000000000000000              __init_array_start
0000000000003fa8 l     O .got   0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000004010 g       .data  0000000000000000              _edata
00000000000011f4  w    F .text  0000000000000017              _Z7compareIiEbT_S0_        //compare函数的符号
0000000000004000  w      .data  0000000000000000              data_start
0000000000002000 g     O .rodata        0000000000000004              _IO_stdin_used
0000000000000000  w    F *UND*  0000000000000000              __cxa_finalize@@GLIBC_2.2.5
0000000000001169 g     F .text  0000000000000025              main
0000000000004008 g     O .data  0000000000000000              .hidden __dso_handle
0000000000001288 g     F .fini  0000000000000000              .hidden _fini
0000000000000000       F *UND*  0000000000000000              __cxa_atexit@@GLIBC_2.2.5
0000000000001080 g     F .text  000000000000002f              _start
0000000000004010 g     O .data  0000000000000000              .hidden __TMC_END__
0000000000004000 g       .data  0000000000000000              __data_start
0000000000004018 g       .bss   0000000000000000              _end
0000000000004010 g       .bss   0000000000000000              __bss_start
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
0000000000001210 g     F .text  0000000000000065              __libc_csu_init
0000000000000000  w      *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000001280 g     F .text  0000000000000005              __libc_csu_fini
0000000000000000       F *UND*  0000000000000000              __libc_start_main@@GLIBC_2.2.5
0000000000000000  w      *UND*  0000000000000000              __gmon_start__
0000000000000000  w      *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4

示例代码4 实例化2次模板一次指定类型,一次参数类型自动推演 两个类型是一样的情况下 并查看编译后.o文件中的 符号表情况

点击查看代码
#include <iostream>
using namespace std;
template<typename T>
bool compare(T x,T y){
    return x,y;
}
int main(){
    bool b =compare<int>(100,200);
    bool b2=compare(400,200);
    return 1;
}
//编译生成.o文件,查看其中的符号表信息, 在其中找到了一处compare函数的符号表
kl@kl-ThinkPad-T580:/data/usershare/code/compile$ objdump -t test1.o
test1.o:     文件格式 elf64-x86-64
SYMBOL TABLE:
0000000000000318 l    d  .interp        0000000000000000              .interp
0000000000000338 l    d  .note.gnu.property     0000000000000000              .note.gnu.property
0000000000000358 l    d  .note.gnu.build-id     0000000000000000              .note.gnu.build-id
000000000000037c l    d  .note.ABI-tag  0000000000000000              .note.ABI-tag
00000000000003a0 l    d  .gnu.hash      0000000000000000              .gnu.hash
00000000000003c8 l    d  .dynsym        0000000000000000              .dynsym
00000000000004a0 l    d  .dynstr        0000000000000000              .dynstr
0000000000000576 l    d  .gnu.version   0000000000000000              .gnu.version
0000000000000588 l    d  .gnu.version_r 0000000000000000              .gnu.version_r
00000000000005c8 l    d  .rela.dyn      0000000000000000              .rela.dyn
00000000000006b8 l    d  .rela.plt      0000000000000000              .rela.plt
0000000000001000 l    d  .init  0000000000000000              .init
0000000000001020 l    d  .plt   0000000000000000              .plt
0000000000001050 l    d  .plt.got       0000000000000000              .plt.got
0000000000001060 l    d  .plt.sec       0000000000000000              .plt.sec
0000000000001080 l    d  .text  0000000000000000              .text
0000000000001298 l    d  .fini  0000000000000000              .fini
0000000000002000 l    d  .rodata        0000000000000000              .rodata
0000000000002008 l    d  .eh_frame_hdr  0000000000000000              .eh_frame_hdr
0000000000002068 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000003d90 l    d  .init_array    0000000000000000              .init_array
0000000000003da0 l    d  .fini_array    0000000000000000              .fini_array
0000000000003da8 l    d  .dynamic       0000000000000000              .dynamic
0000000000003fa8 l    d  .got   0000000000000000              .got
0000000000004000 l    d  .data  0000000000000000              .data
0000000000004010 l    d  .bss   0000000000000000              .bss
0000000000000000 l    d  .comment       0000000000000000              .comment
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000010b0 l     F .text  0000000000000000              deregister_tm_clones
00000000000010e0 l     F .text  0000000000000000              register_tm_clones
0000000000001120 l     F .text  0000000000000000              __do_global_dtors_aux
0000000000004010 l     O .bss   0000000000000001              completed.8059
0000000000003da0 l     O .fini_array    0000000000000000              __do_global_dtors_aux_fini_array_entry
0000000000001160 l     F .text  0000000000000000              frame_dummy
0000000000003d90 l     O .init_array    0000000000000000              __frame_dummy_init_array_entry
0000000000000000 l    df *ABS*  0000000000000000              TemplateTest1.cpp
0000000000002004 l     O .rodata        0000000000000001              _ZStL19piecewise_construct
0000000000004011 l     O .bss   0000000000000001              _ZStL8__ioinit
00000000000011a0 l     F .text  000000000000004d              _Z41__static_initialization_and_destruction_0ii
00000000000011ed l     F .text  0000000000000019              _GLOBAL__sub_I_main
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000021cc l     O .eh_frame      0000000000000000              __FRAME_END__
0000000000000000 l    df *ABS*  0000000000000000              
0000000000002008 l       .eh_frame_hdr  0000000000000000              __GNU_EH_FRAME_HDR
0000000000001000 l     F .init  0000000000000000              _init
0000000000003da8 l     O .dynamic       0000000000000000              _DYNAMIC
0000000000003da0 l       .init_array    0000000000000000              __init_array_end
0000000000003d90 l       .init_array    0000000000000000              __init_array_start
0000000000003fa8 l     O .got   0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000004010 g       .data  0000000000000000              _edata
0000000000001206  w    F .text  0000000000000017              _Z7compareIiEbT_S0_    //此处为compare的函数符号
0000000000004000  w      .data  0000000000000000              data_start
0000000000002000 g     O .rodata        0000000000000004              _IO_stdin_used
0000000000000000  w    F *UND*  0000000000000000              __cxa_finalize@@GLIBC_2.2.5
0000000000001169 g     F .text  0000000000000037              main
0000000000004008 g     O .data  0000000000000000              .hidden __dso_handle
0000000000001298 g     F .fini  0000000000000000              .hidden _fini
0000000000000000       F *UND*  0000000000000000              __cxa_atexit@@GLIBC_2.2.5
0000000000001080 g     F .text  000000000000002f              _start
0000000000004010 g     O .data  0000000000000000              .hidden __TMC_END__
0000000000004000 g       .data  0000000000000000              __data_start
0000000000004018 g       .bss   0000000000000000              _end
0000000000004010 g       .bss   0000000000000000              __bss_start
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
0000000000001220 g     F .text  0000000000000065              __libc_csu_init
0000000000000000  w      *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000001290 g     F .text  0000000000000005              __libc_csu_fini
0000000000000000       F *UND*  0000000000000000              __libc_start_main@@GLIBC_2.2.5
0000000000000000  w      *UND*  0000000000000000              __gmon_start__
0000000000000000  w      *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4

示例代码5 实例化2次模板 两次模板的参数类型不一样 并查看编译后.o文件中的 符号表情况

点击查看代码
#include <iostream>
using namespace std;
template<typename T>
bool compare(T x,T y){
    return x,y;
}
int main(){
    bool b =compare<int>(100,200);
    bool b2=compare(400,200);
    bool b3=compare<double>(1.0,2.0);
    return 1;
}
//编译生成.o文件,查看其中的符号表信息, 在其中找到了两处处compare函数的符号表,一次是int 一次是double
kl@kl-ThinkPad-T580:/data/usershare/code/compile$ g++ TemplateTest1.cpp -o test1.o
kl@kl-ThinkPad-T580:/data/usershare/code/compile$ objdump -t test1.o
test1.o:     文件格式 elf64-x86-64
SYMBOL TABLE:
0000000000000318 l    d  .interp        0000000000000000              .interp
0000000000000338 l    d  .note.gnu.property     0000000000000000              .note.gnu.property
0000000000000358 l    d  .note.gnu.build-id     0000000000000000              .note.gnu.build-id
000000000000037c l    d  .note.ABI-tag  0000000000000000              .note.ABI-tag
00000000000003a0 l    d  .gnu.hash      0000000000000000              .gnu.hash
00000000000003c8 l    d  .dynsym        0000000000000000              .dynsym
00000000000004a0 l    d  .dynstr        0000000000000000              .dynstr
0000000000000576 l    d  .gnu.version   0000000000000000              .gnu.version
0000000000000588 l    d  .gnu.version_r 0000000000000000              .gnu.version_r
00000000000005c8 l    d  .rela.dyn      0000000000000000              .rela.dyn
00000000000006b8 l    d  .rela.plt      0000000000000000              .rela.plt
0000000000001000 l    d  .init  0000000000000000              .init
0000000000001020 l    d  .plt   0000000000000000              .plt
0000000000001050 l    d  .plt.got       0000000000000000              .plt.got
0000000000001060 l    d  .plt.sec       0000000000000000              .plt.sec
0000000000001080 l    d  .text  0000000000000000              .text
00000000000012e8 l    d  .fini  0000000000000000              .fini
0000000000002000 l    d  .rodata        0000000000000000              .rodata
0000000000002020 l    d  .eh_frame_hdr  0000000000000000              .eh_frame_hdr
0000000000002088 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000003d90 l    d  .init_array    0000000000000000              .init_array
0000000000003da0 l    d  .fini_array    0000000000000000              .fini_array
0000000000003da8 l    d  .dynamic       0000000000000000              .dynamic
0000000000003fa8 l    d  .got   0000000000000000              .got
0000000000004000 l    d  .data  0000000000000000              .data
0000000000004010 l    d  .bss   0000000000000000              .bss
0000000000000000 l    d  .comment       0000000000000000              .comment
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
00000000000010b0 l     F .text  0000000000000000              deregister_tm_clones
00000000000010e0 l     F .text  0000000000000000              register_tm_clones
0000000000001120 l     F .text  0000000000000000              __do_global_dtors_aux
0000000000004010 l     O .bss   0000000000000001              completed.8059
0000000000003da0 l     O .fini_array    0000000000000000              __do_global_dtors_aux_fini_array_entry
0000000000001160 l     F .text  0000000000000000              frame_dummy
0000000000003d90 l     O .init_array    0000000000000000              __frame_dummy_init_array_entry
0000000000000000 l    df *ABS*  0000000000000000              TemplateTest1.cpp
0000000000002008 l     O .rodata        0000000000000001              _ZStL19piecewise_construct
0000000000004011 l     O .bss   0000000000000001              _ZStL8__ioinit
00000000000011c0 l     F .text  000000000000004d              _Z41__static_initialization_and_destruction_0ii
000000000000120d l     F .text  0000000000000019              _GLOBAL__sub_I_main
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
000000000000220c l     O .eh_frame      0000000000000000              __FRAME_END__
0000000000000000 l    df *ABS*  0000000000000000              
0000000000002020 l       .eh_frame_hdr  0000000000000000              __GNU_EH_FRAME_HDR
0000000000001000 l     F .init  0000000000000000              _init
0000000000003da8 l     O .dynamic       0000000000000000              _DYNAMIC
0000000000003da0 l       .init_array    0000000000000000              __init_array_end
0000000000003d90 l       .init_array    0000000000000000              __init_array_start
0000000000003fa8 l     O .got   0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000004010 g       .data  0000000000000000              _edata
0000000000001226  w    F .text  0000000000000017              _Z7compareIiEbT_S0_         //compare<int>(int a,int b) 函数符号
0000000000004000  w      .data  0000000000000000              data_start
0000000000002000 g     O .rodata        0000000000000004              _IO_stdin_used
0000000000000000  w    F *UND*  0000000000000000              __cxa_finalize@@GLIBC_2.2.5
0000000000001169 g     F .text  0000000000000057              main
0000000000004008 g     O .data  0000000000000000              .hidden __dso_handle
00000000000012e8 g     F .fini  0000000000000000              .hidden _fini
000000000000123d  w    F .text  0000000000000031              _Z7compareIdEbT_S0_           //compare<double>(double a ,double b) 函数符号
0000000000000000       F *UND*  0000000000000000              __cxa_atexit@@GLIBC_2.2.5
0000000000001080 g     F .text  000000000000002f              _start
0000000000004010 g     O .data  0000000000000000              .hidden __TMC_END__
0000000000004000 g       .data  0000000000000000              __data_start
0000000000004018 g       .bss   0000000000000000              _end
0000000000004010 g       .bss   0000000000000000              __bss_start
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitC1Ev@@GLIBCXX_3.4
0000000000001270 g     F .text  0000000000000065              __libc_csu_init
0000000000000000  w      *UND*  0000000000000000              _ITM_deregisterTMCloneTable
00000000000012e0 g     F .text  0000000000000005              __libc_csu_fini
0000000000000000       F *UND*  0000000000000000              __libc_start_main@@GLIBC_2.2.5
0000000000000000  w      *UND*  0000000000000000              __gmon_start__
0000000000000000  w      *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000       F *UND*  0000000000000000              _ZNSt8ios_base4InitD1Ev@@GLIBCXX_3.4
//我们顺便看一下.o 文件生成的指令   
kl@kl-ThinkPad-T580:/data/usershare/code/compile$ objdump -S test1.o
test1.o:     文件格式 elf64-x86-64
Disassembly of section .init:
0000000000001000 <_init>:
    1000:       f3 0f 1e fa             endbr64 
    1004:       48 83 ec 08             sub    $0x8,%rsp
    1008:       48 8b 05 d9 2f 00 00    mov    0x2fd9(%rip),%rax        # 3fe8 <__gmon_start__>
    100f:       48 85 c0                test   %rax,%rax
    1012:       74 02                   je     1016 <_init+0x16>
    1014:       ff d0                   callq  *%rax
    1016:       48 83 c4 08             add    $0x8,%rsp
    101a:       c3                      retq   
Disassembly of section .plt:
0000000000001020 <.plt>:
    1020:       ff 35 8a 2f 00 00       pushq  0x2f8a(%rip)        # 3fb0 <_GLOBAL_OFFSET_TABLE_+0x8>
    1026:       f2 ff 25 8b 2f 00 00    bnd jmpq *0x2f8b(%rip)        # 3fb8 <_GLOBAL_OFFSET_TABLE_+0x10>
    102d:       0f 1f 00                nopl   (%rax)
    1030:       f3 0f 1e fa             endbr64 
    1034:       68 00 00 00 00          pushq  $0x0
    1039:       f2 e9 e1 ff ff ff       bnd jmpq 1020 <.plt>
    103f:       90                      nop
    1040:       f3 0f 1e fa             endbr64 
    1044:       68 01 00 00 00          pushq  $0x1
    1049:       f2 e9 d1 ff ff ff       bnd jmpq 1020 <.plt>
    104f:       90                      nop
Disassembly of section .plt.got:
0000000000001050 <__cxa_finalize@plt>:
    1050:       f3 0f 1e fa             endbr64 
    1054:       f2 ff 25 75 2f 00 00    bnd jmpq *0x2f75(%rip)        # 3fd0 <__cxa_finalize@GLIBC_2.2.5>
    105b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
Disassembly of section .plt.sec:
0000000000001060 <__cxa_atexit@plt>:
    1060:       f3 0f 1e fa             endbr64 
    1064:       f2 ff 25 55 2f 00 00    bnd jmpq *0x2f55(%rip)        # 3fc0 <__cxa_atexit@GLIBC_2.2.5>
    106b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
0000000000001070 <_ZNSt8ios_base4InitC1Ev@plt>:
    1070:       f3 0f 1e fa             endbr64 
    1074:       f2 ff 25 4d 2f 00 00    bnd jmpq *0x2f4d(%rip)        # 3fc8 <_ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4>
    107b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
Disassembly of section .text:
0000000000001080 <_start>:
    1080:       f3 0f 1e fa             endbr64 
    1084:       31 ed                   xor    %ebp,%ebp
    1086:       49 89 d1                mov    %rdx,%r9
    1089:       5e                      pop    %rsi
    108a:       48 89 e2                mov    %rsp,%rdx
    108d:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
    1091:       50                      push   %rax
    1092:       54                      push   %rsp
    1093:       4c 8d 05 46 02 00 00    lea    0x246(%rip),%r8        # 12e0 <__libc_csu_fini>
    109a:       48 8d 0d cf 01 00 00    lea    0x1cf(%rip),%rcx        # 1270 <__libc_csu_init>
    10a1:       48 8d 3d c1 00 00 00    lea    0xc1(%rip),%rdi        # 1169 <main>
    10a8:       ff 15 32 2f 00 00       callq  *0x2f32(%rip)        # 3fe0 <__libc_start_main@GLIBC_2.2.5>
    10ae:       f4                      hlt    
    10af:       90                      nop
00000000000010b0 <deregister_tm_clones>:
    10b0:       48 8d 3d 59 2f 00 00    lea    0x2f59(%rip),%rdi        # 4010 <__TMC_END__>
    10b7:       48 8d 05 52 2f 00 00    lea    0x2f52(%rip),%rax        # 4010 <__TMC_END__>
    10be:       48 39 f8                cmp    %rdi,%rax
    10c1:       74 15                   je     10d8 <deregister_tm_clones+0x28>
    10c3:       48 8b 05 0e 2f 00 00    mov    0x2f0e(%rip),%rax        # 3fd8 <_ITM_deregisterTMCloneTable>
    10ca:       48 85 c0                test   %rax,%rax
    10cd:       74 09                   je     10d8 <deregister_tm_clones+0x28>
    10cf:       ff e0                   jmpq   *%rax
    10d1:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    10d8:       c3                      retq   
    10d9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
00000000000010e0 <register_tm_clones>:
    10e0:       48 8d 3d 29 2f 00 00    lea    0x2f29(%rip),%rdi        # 4010 <__TMC_END__>
    10e7:       48 8d 35 22 2f 00 00    lea    0x2f22(%rip),%rsi        # 4010 <__TMC_END__>
    10ee:       48 29 fe                sub    %rdi,%rsi
    10f1:       48 89 f0                mov    %rsi,%rax
    10f4:       48 c1 ee 3f             shr    $0x3f,%rsi
    10f8:       48 c1 f8 03             sar    $0x3,%rax
    10fc:       48 01 c6                add    %rax,%rsi
    10ff:       48 d1 fe                sar    %rsi
    1102:       74 14                   je     1118 <register_tm_clones+0x38>
    1104:       48 8b 05 e5 2e 00 00    mov    0x2ee5(%rip),%rax        # 3ff0 <_ITM_registerTMCloneTable>
    110b:       48 85 c0                test   %rax,%rax
    110e:       74 08                   je     1118 <register_tm_clones+0x38>
    1110:       ff e0                   jmpq   *%rax
    1112:       66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
    1118:       c3                      retq   
    1119:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
0000000000001120 <__do_global_dtors_aux>:
    1120:       f3 0f 1e fa             endbr64 
    1124:       80 3d e5 2e 00 00 00    cmpb   $0x0,0x2ee5(%rip)        # 4010 <__TMC_END__>
    112b:       75 2b                   jne    1158 <__do_global_dtors_aux+0x38>
    112d:       55                      push   %rbp
    112e:       48 83 3d 9a 2e 00 00    cmpq   $0x0,0x2e9a(%rip)        # 3fd0 <__cxa_finalize@GLIBC_2.2.5>
    1135:       00 
    1136:       48 89 e5                mov    %rsp,%rbp
    1139:       74 0c                   je     1147 <__do_global_dtors_aux+0x27>
    113b:       48 8b 3d c6 2e 00 00    mov    0x2ec6(%rip),%rdi        # 4008 <__dso_handle>
    1142:       e8 09 ff ff ff          callq  1050 <__cxa_finalize@plt>
    1147:       e8 64 ff ff ff          callq  10b0 <deregister_tm_clones>
    114c:       c6 05 bd 2e 00 00 01    movb   $0x1,0x2ebd(%rip)        # 4010 <__TMC_END__>
    1153:       5d                      pop    %rbp
    1154:       c3                      retq   
    1155:       0f 1f 00                nopl   (%rax)
    1158:       c3                      retq   
    1159:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
0000000000001160 <frame_dummy>:
    1160:       f3 0f 1e fa             endbr64 
    1164:       e9 77 ff ff ff          jmpq   10e0 <register_tm_clones>
0000000000001169 <main>:
    1169:       f3 0f 1e fa             endbr64 
    116d:       55                      push   %rbp
    116e:       48 89 e5                mov    %rsp,%rbp
    1171:       48 83 ec 10             sub    $0x10,%rsp
    1175:       be c8 00 00 00          mov    $0xc8,%esi
    117a:       bf 64 00 00 00          mov    $0x64,%edi
    117f:       e8 a2 00 00 00          callq  1226 <_Z7compareIiEbT_S0_>   //compare<int>(100,200);
    1184:       88 45 fd                mov    %al,-0x3(%rbp)
    1187:       be c8 00 00 00          mov    $0xc8,%esi
    118c:       bf 90 01 00 00          mov    $0x190,%edi
    1191:       e8 90 00 00 00          callq  1226 <_Z7compareIiEbT_S0_>   //compare(400,200); 和上面调用的函数是一个函数
    1196:       88 45 fe                mov    %al,-0x2(%rbp)
    1199:       f2 0f 10 05 6f 0e 00    movsd  0xe6f(%rip),%xmm0        # 2010 <_ZStL19piecewise_construct+0x8>
    11a0:       00 
    11a1:       48 8b 05 70 0e 00 00    mov    0xe70(%rip),%rax        # 2018 <_ZStL19piecewise_construct+0x10>
    11a8:       66 0f 28 c8             movapd %xmm0,%xmm1
    11ac:       66 48 0f 6e c0          movq   %rax,%xmm0
    11b1:       e8 87 00 00 00          callq  123d <_Z7compareIdEbT_S0_>  //   bool b3=compare<double>(1.0,2.0);  double 类型的函数
    11b6:       88 45 ff                mov    %al,-0x1(%rbp)
    11b9:       b8 01 00 00 00          mov    $0x1,%eax
    11be:       c9                      leaveq 
    11bf:       c3                      retq   
00000000000011c0 <_Z41__static_initialization_and_destruction_0ii>:
    11c0:       f3 0f 1e fa             endbr64 
    11c4:       55                      push   %rbp
    11c5:       48 89 e5                mov    %rsp,%rbp
    11c8:       48 83 ec 10             sub    $0x10,%rsp
    11cc:       89 7d fc                mov    %edi,-0x4(%rbp)
    11cf:       89 75 f8                mov    %esi,-0x8(%rbp)
    11d2:       83 7d fc 01             cmpl   $0x1,-0x4(%rbp)
    11d6:       75 32                   jne    120a <_Z41__static_initialization_and_destruction_0ii+0x4a>
    11d8:       81 7d f8 ff ff 00 00    cmpl   $0xffff,-0x8(%rbp)
    11df:       75 29                   jne    120a <_Z41__static_initialization_and_destruction_0ii+0x4a>
    11e1:       48 8d 3d 29 2e 00 00    lea    0x2e29(%rip),%rdi        # 4011 <_ZStL8__ioinit>
    11e8:       e8 83 fe ff ff          callq  1070 <_ZNSt8ios_base4InitC1Ev@plt>
    11ed:       48 8d 15 14 2e 00 00    lea    0x2e14(%rip),%rdx        # 4008 <__dso_handle>
    11f4:       48 8d 35 16 2e 00 00    lea    0x2e16(%rip),%rsi        # 4011 <_ZStL8__ioinit>
    11fb:       48 8b 05 f6 2d 00 00    mov    0x2df6(%rip),%rax        # 3ff8 <_ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4>
    1202:       48 89 c7                mov    %rax,%rdi
    1205:       e8 56 fe ff ff          callq  1060 <__cxa_atexit@plt>
    120a:       90                      nop
    120b:       c9                      leaveq 
    120c:       c3                      retq   
000000000000120d <_GLOBAL__sub_I_main>:
    120d:       f3 0f 1e fa             endbr64 
    1211:       55                      push   %rbp
    1212:       48 89 e5                mov    %rsp,%rbp
    1215:       be ff ff 00 00          mov    $0xffff,%esi
    121a:       bf 01 00 00 00          mov    $0x1,%edi
    121f:       e8 9c ff ff ff          callq  11c0 <_Z41__static_initialization_and_destruction_0ii>
    1224:       5d                      pop    %rbp
    1225:       c3                      retq   
0000000000001226 <_Z7compareIiEbT_S0_>:  // compare<int>(int a, int b)
    1226:       f3 0f 1e fa             endbr64 
    122a:       55                      push   %rbp
    122b:       48 89 e5                mov    %rsp,%rbp
    122e:       89 7d fc                mov    %edi,-0x4(%rbp)
    1231:       89 75 f8                mov    %esi,-0x8(%rbp)
    1234:       83 7d f8 00             cmpl   $0x0,-0x8(%rbp)
    1238:       0f 95 c0                setne  %al
    123b:       5d                      pop    %rbp
    123c:       c3                      retq   
000000000000123d <_Z7compareIdEbT_S0_>:     //compare<double>(1.0,2.0); double 类型的函数
    123d:       f3 0f 1e fa             endbr64 
    1241:       55                      push   %rbp
    1242:       48 89 e5                mov    %rsp,%rbp
    1245:       f2 0f 11 45 f8          movsd  %xmm0,-0x8(%rbp)
    124a:       f2 0f 11 4d f0          movsd  %xmm1,-0x10(%rbp)
    124f:       66 0f ef c0             pxor   %xmm0,%xmm0
    1253:       66 0f 2e 45 f0          ucomisd -0x10(%rbp),%xmm0
    1258:       0f 9a c0                setp   %al
    125b:       ba 01 00 00 00          mov    $0x1,%edx
    1260:       66 0f ef c0             pxor   %xmm0,%xmm0
    1264:       66 0f 2e 45 f0          ucomisd -0x10(%rbp),%xmm0
    1269:       0f 45 c2                cmovne %edx,%eax
    126c:       5d                      pop    %rbp
    126d:       c3                      retq   
    126e:       66 90                   xchg   %ax,%ax
0000000000001270 <__libc_csu_init>:
    1270:       f3 0f 1e fa             endbr64 
    1274:       41 57                   push   %r15
    1276:       4c 8d 3d 13 2b 00 00    lea    0x2b13(%rip),%r15        # 3d90 <__frame_dummy_init_array_entry>
    127d:       41 56                   push   %r14
    127f:       49 89 d6                mov    %rdx,%r14
    1282:       41 55                   push   %r13
    1284:       49 89 f5                mov    %rsi,%r13
    1287:       41 54                   push   %r12
    1289:       41 89 fc                mov    %edi,%r12d
    128c:       55                      push   %rbp
    128d:       48 8d 2d 0c 2b 00 00    lea    0x2b0c(%rip),%rbp        # 3da0 <__do_global_dtors_aux_fini_array_entry>
    1294:       53                      push   %rbx
    1295:       4c 29 fd                sub    %r15,%rbp
    1298:       48 83 ec 08             sub    $0x8,%rsp
    129c:       e8 5f fd ff ff          callq  1000 <_init>
    12a1:       48 c1 fd 03             sar    $0x3,%rbp
    12a5:       74 1f                   je     12c6 <__libc_csu_init+0x56>
    12a7:       31 db                   xor    %ebx,%ebx
    12a9:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    12b0:       4c 89 f2                mov    %r14,%rdx
    12b3:       4c 89 ee                mov    %r13,%rsi
    12b6:       44 89 e7                mov    %r12d,%edi
    12b9:       41 ff 14 df             callq  *(%r15,%rbx,8)
    12bd:       48 83 c3 01             add    $0x1,%rbx
    12c1:       48 39 dd                cmp    %rbx,%rbp
    12c4:       75 ea                   jne    12b0 <__libc_csu_init+0x40>
    12c6:       48 83 c4 08             add    $0x8,%rsp
    12ca:       5b                      pop    %rbx
    12cb:       5d                      pop    %rbp
    12cc:       41 5c                   pop    %r12
    12ce:       41 5d                   pop    %r13
    12d0:       41 5e                   pop    %r14
    12d2:       41 5f                   pop    %r15
    12d4:       c3                      retq   
    12d5:       66 66 2e 0f 1f 84 00    data16 nopw %cs:0x0(%rax,%rax,1)
    12dc:       00 00 00 00 
00000000000012e0 <__libc_csu_fini>:
    12e0:       f3 0f 1e fa             endbr64 
    12e4:       c3                      retq   
Disassembly of section .fini:
00000000000012e8 <_fini>:
    12e8:       f3 0f 1e fa             endbr64 
    12ec:       48 83 ec 08             sub    $0x8,%rsp
    12f0:       48 83 c4 08             add    $0x8,%rsp
    12f4:       c3                      retq   

如果compare(100,1.1) // 编译器推演失败 可以 comare(100,1.1);让编译器强转

函数模板是无法编译的,也不进行编译的,函数模板在调用点发生模板实例化动作,被实例化化后 成为模板函数,模板函数才是真正参与编译的

关于模板特例化
如果有compare("aaa",bbb“”); 此时模板会自动推到出如下
compare<const char *>(const char * x,const char * y){
return x>y;
}

上面的比较方式会去比较两个指针地址大小,这种方式不是我们想要的逻辑,所以我们需要根据const char * 写一个特殊的实现方法逻辑如下
template<>
bool compare<const char *>(const char *x ,const char * y){
return strcmp(x,y);
}
那么上面这个函数就叫做模板的特例化 特例化特殊在不再由编译器自动生成函数,使用自己的实现方式


普通函数和函数模板选择问题 示例代码

点击查看代码
如果有
//这是个函数模板
template<>
bool compare<const char *>(const char *x ,const char * y){
     return strcmp(x,y);
}
//这是一个普通的函数
bool compare(const char *x ,const char * y){
     return strcmp(x,y);
}
有
bool b=compare("aa","bb");//那么编译器会优选能匹配的普通的函数,避免编译器再去生成函数
bool b1=compare<const char *>("aa","bb");//这个时候会使用模板特例化
//所以我们会遇到 函数模板, 模板特例化, 普通函数都可以匹配调用的时候,如何选择需要知道,自动推演有普通函数能用的,用普通函数,没有普通函数如果有模板特例化的用特例化,没有特例化的,编译器去生成指定类型函数

下面我们看一下模板和调用点分文件编写遇到的问题

只有函数模板,编译后查看符号表情况,点击查看代码
// test1.cpp 代码如下
#include <iostream>
#include <cstring>
using namespace std;
//这是一个函数模板
template<typename T>
bool compare(T x,T y){
    return x,y;
}
//test1.cpp 编译后 符号表情况如下,编译后没有 函数符号
uos20@uos20-PC:~/Desktop/CPP$ g++ -c test1.cpp -o test1.o -g
uos20@uos20-PC:~/Desktop/CPP$ objdump -t test1.o
test1.o:     文件格式 elf64-x86-64
SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test1.cpp
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata        0000000000000000 .rodata
0000000000000000 l     O .rodata        0000000000000001 _ZStL19piecewise_construct
0000000000000000 l     O .bss   0000000000000001 _ZStL8__ioinit
0000000000000000 l     F .text  000000000000003e _Z41__static_initialization_and_destruction_0ii
000000000000003e l     F .text  0000000000000015 _GLOBAL__sub_I_test1.cpp
0000000000000000 l    d  .init_array    0000000000000000 .init_array
0000000000000000 l    d  .debug_info    0000000000000000 .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000 .debug_abbrev
0000000000000000 l    d  .debug_aranges 0000000000000000 .debug_aranges
0000000000000000 l    d  .debug_line    0000000000000000 .debug_line
0000000000000000 l    d  .debug_str     0000000000000000 .debug_str
0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
0000000000000000 l    d  .comment       0000000000000000 .comment
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitC1Ev
0000000000000000         *UND*  0000000000000000 .hidden __dso_handle
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitD1Ev
0000000000000000         *UND*  0000000000000000 __cxa_atexit
有函数模板及一个特例化,编译后查看符号表情况,点击查看代码
// test1.cpp 代码如下
#include <iostream>
#include <cstring>
using namespace std;
//这是一个函数模板
template<typename T>
bool compare(T x,T y){
    return x,y;
}
//模板特例化
template<>
bool compare(const char * x, const char * y){
   return strcmp(x,y);
}
//test1.cpp 编译后 符号表情况如下,编译后没有 函数符号
uos20@uos20-PC:~/Desktop/CPP$ g++ -c test1.cpp -o test1.o -g
uos20@uos20-PC:~/Desktop/CPP$ objdump -t test1.o
test1.o:     文件格式 elf64-x86-64
SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test1.cpp
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata        0000000000000000 .rodata
0000000000000000 l     O .rodata        0000000000000001 _ZStL19piecewise_construct
0000000000000000 l     O .bss   0000000000000001 _ZStL8__ioinit
000000000000002a l     F .text  000000000000003e _Z41__static_initialization_and_destruction_0ii
0000000000000068 l     F .text  0000000000000015 _GLOBAL__sub_I__Z7compareIPKcEbT_S2_    // 特例化函数符号compare
0000000000000000 l    d  .init_array    0000000000000000 .init_array
0000000000000000 l    d  .debug_info    0000000000000000 .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000 .debug_abbrev
0000000000000000 l    d  .debug_aranges 0000000000000000 .debug_aranges
0000000000000000 l    d  .debug_line    0000000000000000 .debug_line
0000000000000000 l    d  .debug_str     0000000000000000 .debug_str
0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
0000000000000000 l    d  .comment       0000000000000000 .comment
0000000000000000 g     F .text  000000000000002a _Z7compareIPKcEbT_S2_
0000000000000000         *UND*  0000000000000000 strcmp
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitC1Ev
0000000000000000         *UND*  0000000000000000 .hidden __dso_handle
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitD1Ev
0000000000000000         *UND*  0000000000000000 __cxa_atexit
有函数模板及一个特例化和一个普通函数,编译后查看符号表情况,点击查看代码
// test1.cpp 代码如下
#include <iostream>
#include <cstring>
using namespace std;
//这是一个函数模板
template<typename T>
bool compare(T x,T y){
    return x,y;
}
//模板特例化
template<>
bool compare(const char * x, const char * y){
   return strcmp(x,y);
}
//这是一个普通的函数,不是模板,与模板无关
bool  compare( const char  * x,  const char  * y){
    return x>y;
}
//编译完成后,我们再符号表中 看到两处 compare ,一处是特例化,一处是 普通compare函数
uos20@uos20-PC:~/Desktop/CPP$ g++ -c test1.cpp -o test1.o -g
uos20@uos20-PC:~/Desktop/CPP$ objdump -t test1.o
test1.o:     文件格式 elf64-x86-64
SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test1.cpp
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata        0000000000000000 .rodata
0000000000000000 l     O .rodata        0000000000000001 _ZStL19piecewise_construct
0000000000000000 l     O .bss   0000000000000001 _ZStL8__ioinit
0000000000000043 l     F .text  000000000000003e _Z41__static_initialization_and_destruction_0ii
0000000000000081 l     F .text  0000000000000015 _GLOBAL__sub_I__Z7compareIPKcEbT_S2_
0000000000000000 l    d  .init_array    0000000000000000 .init_array
0000000000000000 l    d  .debug_info    0000000000000000 .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000 .debug_abbrev
0000000000000000 l    d  .debug_aranges 0000000000000000 .debug_aranges
0000000000000000 l    d  .debug_line    0000000000000000 .debug_line
0000000000000000 l    d  .debug_str     0000000000000000 .debug_str
0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
0000000000000000 l    d  .comment       0000000000000000 .comment
0000000000000000 g     F .text  000000000000002a _Z7compareIPKcEbT_S2_  //compare 函数符号
0000000000000000         *UND*  0000000000000000 strcmp
000000000000002a g     F .text  0000000000000019 _Z7comparePKcS0_    //compare函数符号
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitC1Ev
0000000000000000         *UND*  0000000000000000 .hidden __dso_handle
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitD1Ev
0000000000000000         *UND*  0000000000000000 __cxa_atexit
分文件编写,测试代码1,点击查看代码
// test1.cpp
#include <iostream>
#include <cstring>
using namespace std;
//这是一个函数模板
template<typename T>
bool compare(T x,T y){
    return x,y;
}
//test2.cpp
#include <iostream>
#include <cstring>
using namespace std;
template<typename T>
bool compare(T x, T y);
int main() {
   bool b1 = compare<int>(1, 2);
   bool b2 = compare<double>(100.1, 200.1);
   return 1;
}
// 编译 报 两处错  
//无法解析的外部符号 "bool __cdecl compare<double>(double,double)
//无法解析的外部符号 "bool __cdecl compare<int>(int,int)
//为什么会出现链接错误?我先看一下test2.cpp编译后的符号表情况 如下
uos20@uos20-PC:~/Desktop/CPP$ g++ -c test2.cpp -o test2.o -g
uos20@uos20-PC:~/Desktop/CPP$ objdump -t test2.o
test2.o:     文件格式 elf64-x86-64
SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 test2.cpp
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000000 l    d  .rodata        0000000000000000 .rodata
0000000000000000 l     O .rodata        0000000000000001 _ZStL19piecewise_construct
0000000000000000 l     O .bss   0000000000000001 _ZStL8__ioinit
0000000000000039 l     F .text  000000000000003e _Z41__static_initialization_and_destruction_0ii
0000000000000077 l     F .text  0000000000000015 _GLOBAL__sub_I_main
0000000000000000 l    d  .init_array    0000000000000000 .init_array
0000000000000000 l    d  .debug_info    0000000000000000 .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000 .debug_abbrev
0000000000000000 l    d  .debug_aranges 0000000000000000 .debug_aranges
0000000000000000 l    d  .debug_line    0000000000000000 .debug_line
0000000000000000 l    d  .debug_str     0000000000000000 .debug_str
0000000000000000 l    d  .note.GNU-stack        0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame      0000000000000000 .eh_frame
0000000000000000 l    d  .comment       0000000000000000 .comment
0000000000000000 g     F .text  0000000000000039 main
0000000000000000         *UND*  0000000000000000 _Z7compareIiEbT_S0_   //compare<int> 函数符号    UND形式
0000000000000000         *UND*  0000000000000000 _Z7compareIdEbT_S0_   //compare<double> 函数符号 UND形式
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitC1Ev
0000000000000000         *UND*  0000000000000000 .hidden __dso_handle
0000000000000000         *UND*  0000000000000000 _ZNSt8ios_base4InitD1Ev
0000000000000000         *UND*  0000000000000000 __cxa_atexit
//test2.cpp 和 test1.cpp 分离编译,test2.cpp 有 compare<int>函数符号 UND(外部引用) 和 compare<double>函数符号 UND(外部引用)
//然而test1.cpp只是模板 编译时 没有 compare<int>(int a,int b) 和compare<double>(double a, double b)产生编译,
//所以链接的时候,test2.o 的 UND函数需要去其他目标文件中找compare<int>(int a, int b)和compare<double>(double a, double b)的定义,找不到,编译报错
分文件编写,测试代码2,点击查看代码
// test1.cpp
#include <iostream>
#include <cstring>
using namespace std;
//这是一个函数模板
template<typename T>
bool compare(T x,T y){
    return x,y;
}
//模板特例化
template<>
bool compare<const char *>(const char * x, const char * y) {
	return strcmp(x, y);
}
//test2.cpp
#include <iostream>
#include <cstring>
using namespace std;
template<typename T>
bool compare(T x, T y);
int main() {
   bool b3 = compare("aaa", "bbb");
   return 1;
}
//正常编译通过并调用
分文件编写,测试代码3 ,点击查看代码
//test1.cpp
#include <iostream>
#include <cstring>
using namespace std;
//这是一个函数模板
template<typename T>
bool compare(T x, T y) {
	return x, y;
}
//模板特例化
template<>
bool compare<const char *>(const char * x, const char * y) {
	cout << "Template Function" << endl;
	return strcmp(x, y);
}
//这是一个普通的函数,不是模板,与模板无关
bool  compare(const char  * x, const char  * y) {
	cout << "Normal Function" << endl;
	return x>y;
}
//test2.cpp
#include <iostream>
#include <cstring>
using namespace std;
template<typename T>
bool compare(T x, T y);
bool  compare(const char  * x, const char  * y);
int main() {
  bool b3 = compare("aaa", "bbb");
  return 1;
}
//正常编译通过,调用普通函数
分文件编写,测试代码4,点击查看代码
// test1.cpp
#include <iostream>
#include <cstring>
using namespace std;
//这是一个函数模板
template<typename T>
bool compare(T x, T y) {
	return x, y;
}
//模板特例化
template<>
bool compare<const char *>(const char * x, const char * y) {
	cout << "Template Function" << endl;
	return strcmp(x, y);
}
//这是一个普通的函数,不是模板,与模板无关
bool  compare(const char  * x, const char  * y) {
	cout << "Normal Function" << endl;
	return x>y;
}
//编译后, .o文件中有两处 compare函数符号,一处是 普通函数的,一处是 模板特例化函数的
// test2.cpp 情况1  下面test2.cpp编译后,.o文件中没有compare函数符号
#include <iostream>
#include <cstring>
using namespace std;
//模板声明
template<typename T>
bool compare(T x, T y);
int main() {
    system("pause");
    return 1;
}
// test2.cpp 情况2  下面test2.cpp编译后,.o文件中仍然没有compare函数符号
#include <iostream>
#include <cstring>
using namespace std;
//模板声明
template<typename T>
bool compare(T x, T y);
//普通函数声明
bool  compare(const char  * x, const char  * y);
int main() {
    system("pause");
    return 1;
}
// test2.cpp 情况3  下面test2.cpp编译后,.o文件中有compare函数符号,编译报链接错误,因为找不到compare<int>(int a,int b),test1.cpp中只是模板
#include <iostream>
#include <cstring>
using namespace std;
//模板声明
template<typename T>
bool compare(T x, T y);
int main() {
    bool b1 = compare<int>(1, 2);
    system("pause");
    return 1;
}
// test2.cpp 情况4  下面test2.cpp编译后,.o文件中有compare函数符号,编译通过
// bool b1 = compare("AA", "BB");这个调用点会根据模板声明,生成函数符号,
// 而在test1.cpp 中有个模板特例化的实现,所以链接能找到
#include <iostream>
#include <cstring>
using namespace std;
//模板声明
template<typename T>
bool compare(T x, T y);
int main() {
    bool b1 = compare("AA", "BB");
    system("pause");
    return 1;
}
//  test2.cpp 情况5  bool b1 = compare("AA", "BB");如果想调普通函数 那么代码如下,加上普通函数声明
//  bool b1 = compare("AA", "BB");调用点发现有普通函数声明 bool  compare(const char  * x, const char  * y);能匹配
//  那么就按照这个生成函数符号, 而在 test1.cpp中有普通函数的具体实现,所以编译通过,调用普通函数
#include <iostream>
#include <cstring>
using namespace std;
//模板声明
template<typename T>
bool compare(T x, T y);
//普通函数声明
bool  compare(const char  * x, const char  * y);
int main() {
    bool b1 = compare("AA", "BB");
    system("pause");
    return 1;
}
// test2.cpp 情况6  调用点bool b1 = compare("AA", "BB");如果有普通函数声明 bool  compare(const char  * x, const char  * y);
//还是想调用 模板特例化函数,那么要调用点要这么写 bool b1 = compare<const char *>("AA", "BB"); 如下
//在函数调用点 bool b1 = compare<const char *>("AA", "BB"); 会根据声明的模板去生成函数符号,同时在test1.cpp中又有模板特例化函数
//所以能找到匹配的,顺利调用
#include <iostream>
#include <cstring>
using namespace std;
//模板声明
template<typename T>
bool compare(T x, T y);
//普通函数声明
bool  compare(const char  * x, const char  * y);
int main() {
    bool b1 = compare<const char *>("AA", "BB");
    system("pause");
    return 1;
}

前面提到的模板和调用点分文件编写,有链接问题,如何解决?

1:模板声明的文件加上以下语句,强制编译器按照指定类型实例化,生成指定的函数,是的其他文件中的调用点 在链接的时候能找到函数
template bool compare(int,int);
template bool compare(double ,double);

2:加模板声明写在头文件中,在调用点文件include 进来

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。