例如:
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>
提案在水中死亡的原因。
答案 0 :(得分:5)
问题来自ABI中的<unresolved-name>
构造。为什么我们要使用未解析的名称?这都是关于声明匹配和重载的。 C ++14§14.5.6.1/ 3注释,
两个不同的函数模板可能具有相同的函数返回类型和函数参数列表,即使单独的重载分辨率无法区分它们。
您可以在另一个文件中使用其他功能
template <typename T>
void baz(int quux) { std::abort(); }
虽然这个签名不能在同一个文件中和平共存 - 但由于过载歧义而无法命名 - 它可以存在于不同的文件中,因此需要进行明显的修改。
(即使这种共存水平也不能通过所有模板的标准来保证。编译器使用函数模板声明的确切形式来执行声明匹配,这是QOI的问题,因此将声明复制粘贴到定义将倾向于提供精确匹配,而不是与解析为相同签名的另一个函数模板的惊人冲突。参见§14.5.6.1/ 5-6。)
至于default_order
游行的下雨,问题是template-ids隐含地从模板中提取默认参数。因此,只需提及std::set
,用户就可能无意中在签名中具有依赖类型名称。