我被https://stackoverflow.com/a/13296666/53974弄糊涂了,所以我做了一些实验,证实了答案。
只要两个模板不同,即使重载决议无法在它们之间进行选择,它们的特化也可以共存;所以损坏的名称包括模板签名。
由于无法选择重载决议,因此范围内最新的相关声明似乎会影响早期的声明。在下面的示例中,这是可见的两次 -notfun1
并且notfun
具有相同的源但调用不同的专业化,并template void fun<long>(long);
在两个实例中引用不同的模板。(我已经通过检查此来源及其变体的反汇编来确认这两者)。
template<typename T> T var = {};
template long var<long>;
// long var; // Error
void fun(long) {}
template<typename T> void fun(T) {}
template void fun<long>(long); // void fun<long>(long)
void notfun1() {
fun(1L);
fun<long>(2); // Calls void fun<long>(long)
}
template<typename T> struct identity { using type = T; };
template<typename T> void fun(typename identity<T>::type);
template void fun<long>(long); // Generates void fun<long>(identity<long>::type)
//template void fun<long>(typename identity<long>::type); //Ditto, can't write both
void notfun() {
fun(1L);
fun<long>(2); // Calls void fun<long>(identity<long>::type)
}
template<typename T> void fun(typename identity<T>::type) {}
int main() {}
下面,为方便起见,Mac x86_64 上的反汇编;如果你确实看,你会想要专注于callq
目标。
$ c++filt __Z3funIlEvN8identityIT_E4typeE
void fun<long>(identity<long>::type)
$ c++filt __Z3funIlEvT_
void fun<long>(long)
$ g++ -fvisibility=hidden -std=c++17 spec.cpp -o spec; objdump -C --disassemble spec
spec: file format Mach-O 64-bit x86-64
Disassembly of section __TEXT,__text:
0000000100003f40 fun(long):
100003f40: 55 pushq %rbp
100003f41: 48 89 e5 movq %rsp, %rbp
100003f44: 48 89 7d f8 movq %rdi, -8(%rbp)
100003f48: 5d popq %rbp
100003f49: c3 retq
100003f4a: 66 0f 1f 44 00 00 nopw (%rax,%rax)
0000000100003f50 void fun<long>(long):
100003f50: 55 pushq %rbp
100003f51: 48 89 e5 movq %rsp, %rbp
100003f54: 48 89 7d f8 movq %rdi, -8(%rbp)
100003f58: 5d popq %rbp
100003f59: c3 retq
100003f5a: 66 0f 1f 44 00 00 nopw (%rax,%rax)
0000000100003f60 notfun1():
100003f60: 55 pushq %rbp
100003f61: 48 89 e5 movq %rsp, %rbp
100003f64: bf 01 00 00 00 movl $1, %edi
100003f69: e8 d2 ff ff ff callq -46 <__Z3funl>
100003f6e: bf 02 00 00 00 movl $2, %edi
100003f73: e8 d8 ff ff ff callq -40 <__Z3funIlEvT_>
100003f78: 5d popq %rbp
100003f79: c3 retq
100003f7a: 66 0f 1f 44 00 00 nopw (%rax,%rax)
0000000100003f80 notfun():
100003f80: 55 pushq %rbp
100003f81: 48 89 e5 movq %rsp, %rbp
100003f84: bf 01 00 00 00 movl $1, %edi
100003f89: e8 b2 ff ff ff callq -78 <__Z3funl>
100003f8e: bf 02 00 00 00 movl $2, %edi
100003f93: e8 08 00 00 00 callq 8 <__Z3funIlEvN8identityIT_E4typeE>
100003f98: 5d popq %rbp
100003f99: c3 retq
100003f9a: 66 0f 1f 44 00 00 nopw (%rax,%rax)
0000000100003fa0 void fun<long>(identity<long>::type):
100003fa0: 55 pushq %rbp
100003fa1: 48 89 e5 movq %rsp, %rbp
100003fa4: 48 89 7d f8 movq %rdi, -8(%rbp)
100003fa8: 5d popq %rbp
100003fa9: c3 retq
100003faa: 66 0f 1f 44 00 00 nopw (%rax,%rax)
0000000100003fb0 _main:
100003fb0: 55 pushq %rbp
100003fb1: 48 89 e5 movq %rsp, %rbp
100003fb4: 31 c0 xorl %eax, %eax
100003fb6: 5d popq %rbp
100003fb7: c3 retq