在 Itanium C++ ABI 中,为什么模板函数的错位名称不能解析相关的 typedef?
In the Itanium C++ ABI, why does the mangled name for template functions not resolve dependent typedefs?
例如:
template <typename T>
struct foo
{
using bar = int;
};
// _Z3bazi
void baz(foo<int>::bar quux) {
}
template <typename T>
void baz(typename foo<T>::bar quux) {
}
// _Z3bazIiEvN3fooIT_E3barE
template void baz<int>(foo<int>::bar quux);
为什么 baz<int>
的变形形式完全提到了 foo
?怎么不是_Z3bazIiEvi
?
这显然是 C++17 std::default_order<T>
提案搁浅的原因。
问题来自 ABI 中的 <unresolved-name>
构造。为什么我们要使用未解析的名称?这都是关于声明匹配和重载的。 C++14 §14.5.6.1/3 注释,
Two distinct function templates may have identical function return types and function parameter lists, even if overload resolution alone cannot distinguish them.
你可以在不同的文件中有另一个函数,
template <typename T>
void baz(int quux) { std::abort(); }
虽然这个签名不能在同一个文件中和平共存——由于重载歧义,它不能被命名——但它可以存在于不同的文件中,所以它需要一个不同的修改。
(即使是这种级别的共存也不能保证所有模板的标准。编译器使用函数模板声明的确切形式来执行声明匹配是 QOI 的问题,因此复制粘贴声明到一个定义中将倾向于提供一个精确的匹配,而不是与另一个解析为相同签名的函数模板发生令人惊讶的冲突。参见 §14.5.6.1/5-6。)
至于下雨 default_order
的游行,问题是模板 ID 隐式地从模板中提取默认参数。因此,用户可能无意中通过提及 std::set
.
在签名中拥有依赖类型名
例如:
template <typename T>
struct foo
{
using bar = int;
};
// _Z3bazi
void baz(foo<int>::bar quux) {
}
template <typename T>
void baz(typename foo<T>::bar quux) {
}
// _Z3bazIiEvN3fooIT_E3barE
template void baz<int>(foo<int>::bar quux);
为什么 baz<int>
的变形形式完全提到了 foo
?怎么不是_Z3bazIiEvi
?
这显然是 C++17 std::default_order<T>
提案搁浅的原因。
问题来自 ABI 中的 <unresolved-name>
构造。为什么我们要使用未解析的名称?这都是关于声明匹配和重载的。 C++14 §14.5.6.1/3 注释,
Two distinct function templates may have identical function return types and function parameter lists, even if overload resolution alone cannot distinguish them.
你可以在不同的文件中有另一个函数,
template <typename T>
void baz(int quux) { std::abort(); }
虽然这个签名不能在同一个文件中和平共存——由于重载歧义,它不能被命名——但它可以存在于不同的文件中,所以它需要一个不同的修改。
(即使是这种级别的共存也不能保证所有模板的标准。编译器使用函数模板声明的确切形式来执行声明匹配是 QOI 的问题,因此复制粘贴声明到一个定义中将倾向于提供一个精确的匹配,而不是与另一个解析为相同签名的函数模板发生令人惊讶的冲突。参见 §14.5.6.1/5-6。)
至于下雨 default_order
的游行,问题是模板 ID 隐式地从模板中提取默认参数。因此,用户可能无意中通过提及 std::set
.