2009-03-08 3 views
8

저는 C++ 정적 라이브러리를 컴파일하고 있으며 모든 클래스가 템플릿으로되어 있기 때문에 클래스 정의와 구현은 모두 헤더 파일에 있습니다. 결과적으로 (Visual Studio 2005에서) 라이브러리에 올바르게 컴파일하려면 다른 모든 헤더 파일을 포함하는 .cpp 파일을 만들어야합니다.헤더 파일 만 사용하여 C++ .lib 컴파일?

왜 이런가요?

답변

8

컴파일러는 소스 파일에 포함되기 때문에 헤더 파일을 컴파일하지 않습니다. 어떤 컴파일이 일어나기 전에 전처리 기는 포함 된 헤더 파일에서 모든 코드를 가져 와서 포함 된 소스 파일의 소스 파일에 포함시킵니다. 컴파일러가 헤더 파일도 컴파일해야하는 경우, 예를 들어 여러 가지 정의가있을 수 있습니다.

[foo.h] 
void foo(); 

-

[mysource.cpp] 
#include "foo.h" 

int main() 
{ 
    foo(); 
} 

그리고 이것은 컴파일러가 보는 것입니다 :

예, 이것은 전처리가 보는 무엇인가의

[mysource.cpp] 
void foo(); 

int main() 
{ 
    foo(); 
} 
4

.cpp 파일을 만들지 만 여전히 아무 것도받지 못합니다. 템플릿을 라이브러리에 넣으려면 템플릿을 인스턴스화해야합니다.

구체적인 유형으로 템플릿을 인스턴스화하는 방법에 대해 자세히 알아 보려면 http://www.parashift.com/c%2B%2B-faq-lite/templates.html#faq-35.13 여기를보세요.

0

생각해을 표준 템플릿 라이브러리. 템플릿 기반 수업은 다른 프로젝트에서 활용할 때 컴파일됩니다.

0

템플릿이 라이브러리에 컴파일되지 않는 것에 대해 다른 사람들은 진실이라고합니다. 그러나 컴파일러에서 (.cpp 파일에 #include하여) 적어도 구문을 검사하는 방식으로 강제로 표시 할 가치가 있습니다.

+0

존재할 필요가없는 정적 라이브러리 생성을 강요하는 것보다 단위 테스트 세트를 작성하는 것이 좋습니다. 결국, 많은 컴파일러는 템플릿 코드가 호출되지 않으면 템플릿 코드에서 아주 기본적인 오류를 놓치게됩니다. – Tom

2

C++에서 템플릿은 실제 클래스의 메타 정의입니다. 템플릿 기반 클래스를 컴파일 할 때 컴파일러는 실제로 전달 된 특정 데이터 유형에 대해 실제 클래스의 코드를 생성합니다.이 템플릿은 복사 할 "패턴"일뿐입니다.

다음과 같은 코드가있는 경우

 

struct MyTemplate 
{ 
private: 
    float MyValue; 

public: 
    float Get() { return MyValue; } 
    void Set(float value) { MyValue = value; } 
}; 

void main() 
{ 
    MyTemplate v1; 
    MyTemplate v2; 
    v1.Set(5.0f); 
    v2.Set(2); 
    v2.Get(); 
} 
 

무엇 컴파일러가 실제로 보는 것은 당신이 아마 볼 수 있듯이 실제로 인스턴스를 선언 할 때까지, 컴파일러가 실제로 생성하는 어떤 코드를 모르는

 

struct CompilerGeneratedNameFor_MyTemplate_float 
{ 
private: 
    float MyValue; 

public: 
    float Get() { return MyValue; } 
    void Set(float value) { MyValue = value; } 
}; 

struct CompilerGeneratedNameFor_MyTemplate_int 
{ 
private: 
    int MyValue; 

public: 
    int Get() { return MyValue; } 
    void Set(int value) { MyValue = value; } 
}; 

void main() 
{ 
    CompilerGeneratedNameFor_MyTemplate_float v1; 
    CompilerGeneratedNameFor_MyTemplate_int v2; 
    v1.Set(5.0f); 
    v2.Set(2); 
    v2.Get(); 
} 
 

입니다 템플릿의 즉, 템플릿이 실제로 끝날지 모르기 때문에 템플릿을 라이브러리로 컴파일 할 수 없습니다. 좋은 소식은 템플릿 정의가 포함 된 헤더 파일을 배포하는 경우 컴파일하거나 포함시킬 라이브러리가 실제로 필요하지 않다는 것입니다.

또한 '#include'사전 컴파일러 명령은 실제로 '#include'를 해당 파일의 모든 항목으로 바꾸도록 사전 컴파일러에 지시합니다.

1

불필요한 것을 만들려고합니다.

  • 인터페이스 (foo.h)
  • 가 구현 (foo.lib)

는 C++ 템플릿 코드의 경우, 라이브러리의 모든 컴파일해야합니다 : 대부분의 C 라이브러리 (모든 C++ 라이브러리) 두 부분으로 분산 취득 이것이 최종 사용자가 템플릿을 사용하는 방식이기 때문입니다. 미리 컴파일 된 라이브러리를 제공 할 이유가 없습니다. 이 경우,이 같은 라이브러리 배포 생각할 수 :

  • 인터페이스 (foo.h)
  • 구현 (foo-inl.h)

Niel 위에서 말했듯이, 그것은 단지 구현을 가지고 유용하여 자체 테스트 목적을 가지고 있으며, 도서관 자체에서 배포하는 것이 좋습니다. 따라서 코드를 실행하는 단위 테스트 스위트를 별도로 준비해야합니다. 그러나 그 시험은 도서관 그 자체의 일부가되어서는 안됩니다.

0

모든 수업이 템플리트 인 경우 .lib를 생성 할 필요가 없으며 [1] 배포 할 .lib가없는 stlport를 보거나 향상을 취하십시오.

템플릿은 사용될 때 컴파일됩니다.

[1] 엄밀히 말하자면 정규 표현식, iostream 등과 같은 고급 기능을위한 라이브러리를 배포하지만 보조 라이브러리는 다른 템플릿에서 사용되고 템플릿 자체는 라이브러리 형식으로 배포되지 않습니다.

2

코드가 모두 .h 파일이면 코드를 사용하기 위해 정적 라이브러리를 컴파일 할 필요가 없습니다.

모든 코드는 컴파일시 라이브러리에서 사용할 수 있으므로 링크 할 때 아무 것도 필요하지 않습니다.

1

라이브러리가 모두 헤더 파일로 구현 된 경우 라이브러리를 사용하기 위해 이진 파일을 빌드 할 필요가 없습니다. 그것이 말했다. 나는 보통 헤더 개발 라이브러리의 초기 개발 단계에서 .cpp 파일을 만든다. 왜? 컴파일러는 실제로 사용되기 전까지는 템플릿을 컴파일하거나 해석하지 않습니다. .cpp 파일이 있고 거기에 더미 코드가 있으면 템플릿을 인스턴스화 할 때 개발 초기에 구문 오류를 쉽게 찾을 수 있습니다. 그래서 몇 가지 템플릿 코드를 추가 할 수 있습니다 컴파일, 구문 오류 수정, 더 많은 코드를 추가, 컴파일 ... 등. 모든 사람들이 수백 줄의 코드를 추가 한 후에 바보 같은 문법 오류를 찾으려고한다면, 내가 무슨 뜻인지 알게 될 것이다. 일단 내 라이브러리가 단위 테스트를위한 준비가되면, .cpp 파일을 제거하고 단위 테스트에 의존하여 개발을 유도 할 것입니다.

또한 VC++를 사용하여 코드를 컴파일하는 경우 VC++에서 실제로 사용되기 전까지는 모든 템플릿 멤버 함수를 컴파일하지 않습니다. 예 :

template <typename T> 
class MyTemplate 
{ 
public: 
    MyTemplate() {} // default constructor 

    MyTemplate(int) { 
     1 = 2 
     // other syntax error code here 
    } 
}; 

void f() { MyTemplate<int> myt(); } // compile fine in VC 
void g() { MyTemplate<int> myt(1); } // syntax error 

f()는 VC++ 2003에서 제대로 컴파일되지만 g ++은 구문 오류를 포착합니다. VC8과 VC9도 같은 문제가 있다고 생각합니다.