Old-Style Name Mangling for Exported Template Instantiations
One aspect of the Visual C++ conformance work is to allow the overloading of specializations of function templates and regular templates.
For example, the following sample compiles in Visual Studio .NET 2003 but will fail in Visual Studio .NET:
// bc_exported_templ_instan.cpp
template<typename T, typename U>
T ConvertTo(const U &u) {
return static_cast<T>(u);
}
char ConvertTo(const int &i) {
return static_cast<char>(i);
}
int main() {
char c1 = ConvertTo(1);
char c2 = ConvertTo<char, int>(2);
}
To support the overloading of specializations of function templates and regular templates, the compiler changed how it creates decorated names for specializations of function templates. An updated decorated name now includes encoding of the template arguments, as well as encoding of the function parameter and return types. For the functions in the previous example, the C++ compiler in Visual Studio .NET 2003 will generate the following name decorations:
?ConvertTo@@YADABH@Z – char ConvertTo(const int &);
??$ConvertTo@DH@@YADABH@Z – char ConvertTo<char, int>(const int &);
This should not imply any change in the way that you develop your applications. One area where this change does affect users is if the export is a specialization of a function template from a DLL used in an application that has not been recompiled with the new compiler. For example:
// bc_exported_templ_instan2.h
#include <iostream>
#ifdef _DLL_EXPORT
#define DLL_LINKAGE __declspec(dllexport)
#else
#define DLL_LINKAGE __declspec(dllimport)
#endif
template<typename T>
void f(const T &rT) {
std::cout << "i = " << rT << std::endl;
}
template DLL_LINKAGE void f<int>(const int &);
The following code will be compiled to create the DLL:
// bc_exported_templ_instan2.cpp
// compile with: /D_DLL_EXPORT /EHsc /LD
#include "bc_exported_templ_instan2.h"
If you then do:
dumpbin /exports bc_exported_templ_instan2.dll
You see that the decorated name of the exported specialization of the function template is ??$f@H@@YAXABH@Z
.
If an existing application has a dependency on this DLL and this application was built with the Visual C++ compiler in Visual Studio .NET (or an earlier version) and they cannot or do not want to rebuild this application, then they will get a run-time error, because the application will be expecting an entry point with the old name. However, the new DLL will only be exporting a function with the new name.
// bc_exported_templ_instan3.cpp
// compile with: /EHsc /link bc_exported_templ_instan2.lib
#include "bc_exported_templ_instan2.h"
int main() {
f(1);
}
The fix for this problem is to change how the DLL is built so it will export both the old and new name for the specialization of the function template. This is done by using /export to the link program. For example:
cl /D_DLL_EXPORT /EHsc /LD a.cpp /link /export:?f@@YAXABH@Z=??$f@H@@YAXABH@Z
This tells the link to create an export for both the specified names but to have them map to the same symbol.