For example:
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);
Why does the mangled form of baz<int>
mention foo
at all? How come it's not _Z3bazIiEvi
?
This is apparently the reason that the C++17 std::default_order<T>
proposal is dead in the water.
The issue comes from the <unresolved-name>
construct in the ABI. Why would we ever want to use an unresolved name? It's all about declaration matching and overloads. C++14 §14.5.6.1/3 notes,
Two distinct function templates may have identical function return types and function parameter lists, even if overload resolution alone cannot distinguish them.
You can have another function in a different file,
template <typename T>
void baz(int quux) { std::abort(); }
Although this signature can't peacefully coexist in the same file — it cannot be named because of overload ambiguity — it can exist in a different file so it needs a distinct mangling.
(Even this level of coexistence is not guaranteed by the standard for all templates. It's a matter of QOI that the compiler uses the exact form of a function template declaration to perform declaration matching, so that copy-pasting a declaration into a definition will tend to provide an exact match and not a surprising conflict with another function template that resolves to the same signature. See §14.5.6.1/5-6.)
As for raining on default_order
's parade, the problem is that template-ids implicitly pull default arguments from templates. So the user could unintentionally have a dependent typename in a signature just by mentioning std::set
.