考虑以下职能:
template <typename A, typename B>
auto Min(A&& a, B&& b)
-> decltype(a < b ? std::forward<A>(a) : std::forward<B>(b))
{
return a < b ? std::forward<A>(a) : std::forward<B>(b);
}片段Min(0, 1)导致模板被实例化为Min<int, int>。奇怪的是,Min ( g++ )和clang (我的代码)的错误名称是_Z3MinIiiEDTqultfp_fp0_cl7forwardIT_Efp_Ecl7forwardIT0_Efp0_EEOS0_OS1_ (又名:decltype (({parm#1}<{parm#2})?((forward<int>)({parm#1})) : ((forward<int>)({parm#2}))) Min<int, int>(int&&, int&&))。换句话说,用于推断返回类型的表达式是故障名称的一部分。就我个人而言,我期望类似于:_Z3MinIiiET_OS0_OT0_ (又名:int Min<int, int>(int&&, int&&))之类的更理智的东西。,为什么不是这样呢?
似乎g++只将decltype表达式放在实际需要的情况下,因为这些表单都是_Z3Maxii。
auto Max(int x, int y) -> intauto Max(int x, int y) -> decltype(0)发布于 2012-11-08 19:51:54
如果重载函数模板,则这些函数模板(称为函数模板专门化)生成的函数需要不同。因此,C++标准指定函数模板专门化的签名包括生成专门化的函数模板的签名。
否则,如果两个模板都将实例化具有相同函数类型的函数,则它们将发生冲突。
发布于 2012-11-08 19:12:08
gcc正在使用“意大利C++ ABI”用于残废,它指定
如果
decltype的操作数表达式不依赖于实例化,则直接对结果类型进行编码。例如: int x;模板自动f(T )->decltype(X);//模板签名//的损坏中的返回类型被编码为"i“。模板自动f(T )->decltype(P);//模板签名//损坏中的返回类型被编码为"Dtfp_E“。void (Int);模板自动f(T )->decltype(g(P));//模板签名//的损坏中的返回类型编码为"DTcl1gfp_E“。
第三个例子是OP的简化版本,它也直接编码整个表达式,因为它依赖于实例化。定义为
表达式是实例化依赖的,如果它是类型依赖的或值依赖的,或者它有一个类型依赖或值依赖的子表达式。例如,如果
p是一个依赖于类型的标识符,则表达式sizeof(sizeof(p))既不依赖于类型,也不依赖于值,但它是实例化依赖的(如果模板参数替换后p的类型不完整,则该表达式可能无效)。类似地,如果源代码中表示的类型包含实例化相关表达式,则该类型与实例化相关.例如,类型表单double[sizeof(sizeof(p))](p是一个依赖于类型的标识符)是实例化的。
关键是实例化相关表达式“可能在替换后无效”,这很可能是它们在残缺状态下留在未计算形式中的原因。
发布于 2021-07-22 10:09:04
我被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 retqhttps://stackoverflow.com/questions/13294985
复制相似问题