2009-10-16 11 views
1

다른 질문에서 언급했듯이 나는 this article을 발견했습니다. MSVC7.1을 통해 1.40으로 부스트를 컴파일하고 몇 가지 C4251 경고가 나타 났을 때 문제가 발생했습니다.템플릿 코드 내보내기 = 위험합니까? (MSVC)

이제 기사를 읽은 후 다음과 같은 질문을 던집니다. 템플릿 코드를 내보내는 것이 일반적으로 바람직하지 않습니까?

class DLLEXPORT_MACRO AClass 
{ 
public: 
    std::vector<int> getVecCopy() { return myVec; } 
    ... 
} 

이 코드는 MSVC7.1을 통해 DLL로 컴파일됩니다. 이 코드는 다른 MSVC7.1 코드에서 참조 할 때 오류를 생성하지 않지만 MSVC8 코드에서이 DLL을 참조하면 (메모리 정렬 문제가 발생합니까?)시 이 충돌합니다.

분명히 나쁘기 때문에 ... 템플릿 코드를 내보내는 문제에 대처하는 "모범 사례"는 무엇입니까?

답변

6

이것은 std :: vector가 다르거 나 컴파일러 버전에 따라 다를 수 있으므로 나쁜 생각입니다. 그러나 std :: vector의 mangling 이름은 컴파일러 버전에 따라 다르므로로드 타임에 실패 할 수 있습니다 (이름 맹 글링의 근거가 됨).

이 링크 타임 오류는이를 지원하는 컴파일러를 구입하는 것 외에 개발자가 실제로 시행 할 수없는 것입니다. 다른 해결책은 DLL 인터페이스에서 템플릿 유형을 완전히 보존하는 것입니다. 그들을 사적인 일원으로 삼으십시오.

이 문제는 템플릿에만 적용되지 않습니다. std::string이 typedef 대신 UDT이고 컴파일러 런타임에 의해 제공되는 순간을 상상해보십시오. 컴파일러 버전과 컴파일러 공급 업체 간에는 여전히 변할 수 있습니다. DLL 인터페이스에서는 여전히 사용할 수 없습니다.

이러한 이유로 실제 솔루션은 0입니다. 사용 C, 1. COM을 사용하거나 2. 단일 컴파일러 버전으로 해결하십시오.

+3

이것은 일반적인 C++ ABI 문제의 한 부분으로 악명 높은 "취약한 기본 클래스"문제는 또 다른 특수한 경우입니다. DLL에서 템플릿 인터페이스를 내보내는 일은 기다리고있는 재앙 일뿐입니다. 내가 선호하는 솔루션은 MSalters '0의 변형입니다. DLL에서 직접 C++을 내보내고, C 바인딩이있는 얇은 내보내기 레이어를 제공하고, 개체 포인터가 불투명 한 핸들처럼 클라이언트에 앞뒤로 전달됩니다. 그런 식으로 클라이언트는 컴파일러 관련 개체 내부에서 직접 원숭이를 처리 할 수 ​​없으므로이 문제가 발생하지 않습니다. –

+0

통찰력에 감사드립니다. (1)은 고려되지 않지만 Bob이 말했듯이 (0) 또는 (0 ')으로 살 수 있다고 생각합니다. 사실, 왜 boost :: program_options가 "일어날 대기 재앙"을 만들고 있는지 궁금합니다. – msi

0

불행히도 실제로 템플릿 코드를 내보낼 방법이 없습니다. 외부 라이브러리는 일반적으로 모든 템플릿에 대한 소스 코드를 제공합니다. 때로는 템플릿에 독점 코드를 숨기고 자하는 템플릿이 아닌 도우미 클래스를 사용하는 경우가 있습니다. 그러나 기본적으로 이렇게 할 방법이 없습니다.

관련 문제