내보낸 템플릿 인스턴스화에 대한 이전 스타일의 이름 관리
업데이트: 2007년 11월
Visual C++ 규칙 작업에는 함수 템플릿 및 일반 템플릿 특수화의 오버로드를 허용하는 기능이 있습니다.
예를 들어 다음 샘플은 Visual Studio .NET 2003에서는 컴파일되지만 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);
}
함수 템플릿 및 일반 템플릿 특수화의 오버로드를 지원하기 위해 컴파일러에서 함수 템플릿 특수화의 데코레이팅된 이름을 만드는 방법을 변경했습니다. 이제 업데이트된 데코레이팅된 이름에는 템플릿 인수의 인코딩과 함수 매개 변수 및 반환 형식의 인코딩이 포함됩니다. 이전 예제에 있는 함수의 경우 Visual Studio .NET 2003의 C++ 컴파일러는 다음 이름 데코레이션을 생성합니다.
?ConvertTo@@YADABH@Z – char ConvertTo(const int &);
??$ConvertTo@DH@@YADABH@Z – char ConvertTo<char, int>(const int &);
이로 인해 사용자가 응용 프로그램을 개발하는 방식이 변경되어서는 안 됩니다. 이러한 변경 사항이 사용자에게 영향을 주는 경우는 내보내기가 새 컴파일러로 다시 컴파일되지 않은 응용 프로그램에 사용된 DLL의 함수 템플릿 특수화인 경우입니다. 예를 들면 다음과 같습니다.
// 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 &);
다음 코드는 컴파일되어 DLL을 만듭니다.
// bc_exported_templ_instan2.cpp
// compile with: /D_DLL_EXPORT /EHsc /LD
#include "bc_exported_templ_instan2.h"
그런 다음 다음을 수행합니다.
dumpbin /exports bc_exported_templ_instan2.dll
함수 템플릿의 내보낸 특수화에 대한 데코레이팅된 이름은 ??$f@H@@YAXABH@Z입니다.
기존 응용 프로그램이 이 DLL에 종속되어 있고 이 응용 프로그램이 Visual Studio .NET 또는 이전 버전에서 Visual C++ 컴파일러로 빌드되었으며 이 응용 프로그램을 다시 빌드할 수 없거나 빌드하지 않으려는 경우 응용 프로그램에서 이전 이름으로 진입점을 예상하기 때문에 런타임 오류가 발생합니다. 새 DLL은 새 이름으로만 함수를 내보냅니다.
// bc_exported_templ_instan3.cpp
// compile with: /EHsc /link bc_exported_templ_instan2.lib
#include "bc_exported_templ_instan2.h"
int main() {
f(1);
}
이 문제에 대한 수정 방법은 함수 템플릿의 특수화에 대해 이전 이름과 새 이름을 모두 내보내도록 DLL 빌드 방식을 변경하는 것입니다. 이는 링크 프로그램에 대해 /export를 사용하여 수행할 수 있습니다. 예를 들면 다음과 같습니다.
cl /D_DLL_EXPORT /EHsc /LD a.cpp /link /export:?f@@YAXABH@Z=??$f@H@@YAXABH@Z
이 코드는 지정된 이름 둘 다에 대해 내보내기를 만들지만 이들을 동일한 기호에 매핑하도록 해당 링크에 지시합니다.