2017-12-15 6 views
-1

편집 CPP 파일에 선언 된 소스와, Windows에서 템플릿 전문화를 수출 dll을하는 (편집) cpp 파일에 정의되어 있습니다 (순수하게 템플리트를 내보낼 목적으로).어떻게이 질문은 많이</p> <p>I는 DLL에서 템플릿 전문화를 수출하려고 수정되었습니다

머리글에서 dllimport/export를 사용한 첫 번째 시도 ("첫 번째 시도")가 컴파일 및 런타임에서 작동하는 것으로 판명되었지만 C4661 경고가 발생했습니다 (명시 적 템플릿 인스턴스화 요청에 적합한 정의가 제공되지 않음).). 이것이 내가 처음에 질문 한 내용입니다. 그러나 @AnT 응답은 내 실수를 보여 주었고 "Second Attempt"로이를 수정하려고 시도했으나 경고도 나타납니다.

첫번째 시도

foo.h

#ifndef _foo_h_ //header guard 
#define _foo_h_ 

#ifdef EXAMPLE_FOO_EXPORTS 
#define EXAMPLE_FOO_EXPORT __declspec(dllexport) 
#define EXAMPLE_FOO_EXTERN 
#else 
#define EXAMPLE_FOO_EXPORT __declspec(dllimport) 
#define EXAMPLE_FOO_EXTERN extern 
#endif 

template<typename _Type> 
class foo 
{ 
public: 
    _Type value(); 
}; 

EXAMPLE_FOO_EXTERN template class EXAMPLE_FOO_EXPORT foo<int>; 

#endif//_foo_h_ 

foo.cpp에

#include "foo.h" 

template<typename _Type> 
_Type foo<_Type>::value() 
{ 
    return (_Type)1; 
} 

I 출력 할 DLL 테스트 코드의 일부 값을 갖는다.

Test.cpp에

#include "foo.h" 

int readValue() 
{ 
    foo<int> test; 

    return test.value(); 
} 

두 번째 시도

, 표준의 개미의 참고 @ 떨어져가는 CPP의 작품 인스턴스하지만이 부여 된 또 다른 문제 (왼쪽하고 모든 VC입니다 -부). 아래의 코드를 변경하여 인스턴스화가 cpp (표준 및 dll 내보내기 작동)에서 수행되는지 확인하기 위해 C4251 경고가 표시됩니다. 'bar :: value': 클래스 'foo'는 dll 인터페이스가 있어야합니다. struct bar의 클라이언트가 사용합니다.

foo.h

#ifndef _foo_h_ //header guard 
#define _foo_h_ 

#ifdef EXAMPLE_FOO_EXPORTS 
#define EXAMPLE_FOO_EXPORT __declspec(dllexport) 
#define EXAMPLE_FOO_EXTERN 
#else 
#define EXAMPLE_FOO_EXPORT __declspec(dllimport) 
#define EXAMPLE_FOO_EXTERN extern 
#endif 

template<typename _Type> 
class foo 
{ 
public: 
    _Type value(); 
}; 

typedef foo<int> fooInt; 

#ifndef EXAMPLE_FOO_EXPORTS 
extern template class __declspec(dllimport) foo<int>; 
#endif 

struct EXAMPLE_FOO_EXPORT bar 
{ 
    fooInt value; 
}; 
#endif//_foo_h_ 

foo.cpp에

#include "foo.h" 

template<typename _Type> 
_Type foo<_Type>::value() 
{ 
    return (_Type)1; 
} 

#ifdef EXAMPLE_FOO_EXPORTS 
template class __declspec(dllexport) foo<int>; 
#endif 

나는 그것이 __declspec (dllexport)와 cpp에있는 인스턴스화하기 전에 바 구조체 foo는 템플릿을 인스턴스화 믿습니다. "이것은 미친 짓이야,이 모든 잘못이고 왜 이러는거야?", 이것에 대한 방법이 있습니까 아니면이 dll 가져 오기/내보내기의 단지 독특한 무엇입니까 그리고 그것이 무엇입니까?

+0

헤더 파일에서 명시적인 인스턴스화 정의를 수행하는 이유는 무엇입니까? 이것은 일어날 대기 ODR 위반입니다. – AnT

+0

** C4661 경고 **에 대해 설명하지 않았습니다. 다른 컴파일러 (예 : [GCC] (http://gcc.gnu.org/),'g ++ -Wall -Wextra -g')를 사용해보십시오. 그러면 또 다른 * 경고가 나옵니다. 하지만 실제로는 소스 코드를 개선하는 것이 좋습니다. –

+0

C4661 : 명시 적 템플릿 인스턴스화 요청에 적절한 정의가 제공되지 않습니다. 그리고 이것은 순전히 dll 수입/수출 문제입니다. @AnT가 언급 한대로 인스턴스화를 cpp 파일로 이동하는 것은 올바른 방법이며 (대부분의 다른 컴파일러도이를 만족해야합니다). 내가 실수로 만든 이유는 Windows dll에 필요한 dllexport 요구 사항을 해결하려고하기 때문입니다. – Krazer

답변

1

언어 사양은

14.7.2 명시 인스턴스를 말한다
9 클래스 템플릿 특수화를 명시 적으로 클래스 템플릿 특수화를 인스턴스화 만의 명시 적 인스턴스 정의입니다 이름을 명시 적 인스턴스화 정의 인스턴스화 시점에 정의 된 멤버.귀하의 경우에는

하지은 회원이 아직 정의되지 않은 명시 적 인스턴스화의 시점에서 이후, foo<int>::value()에 대한 명시 적 인스턴스화 정의를 제공합니까 사용자의 명시 적 인스턴스 정의.

C4661의 목적은 그 문제를 알려주는 것입니다. dllexport -ed 엔티티에 MSVC가 특별한 대우를 적용하여 궁극적으로 코드가 올바르게 링크되도록하는 것이 가능합니다. 그러나 언어 관점에서이 문제가 있습니다.

+0

귀하의 답변에 따라 질문을 수정했습니다. 편집 섹션을 참조하십시오. dllexport 선언 헤더에서 인스턴스화했습니다. 내가 cpp에서 처리 할 수 ​​있지만 다른 문제가있다. 표준 정확성을 위해, cpp에서 인스턴스화하는 것은 내가 유지하는 방법이 될 것이지만이 시점에서 다른 경고를 지우려고 노력할 것입니다. – Krazer