c++ 에서 static library 와 template

c++에서 템플릿의 구현체는 기본적으로 해더파일에 구현해야 한다.
템플릿의 내용을 cpp안에 넣어도 해당 코드를 라이브러리 형태로 다른곳에서 참조하지만 않으면 문제가 없다.
문제는 해당 cpp파일을 라이브러리(.a)로 만든다음에, 다른 프로그램이 링킹하려고 한다면 심볼을 찾을 수 없다는 오류가 발생한다.

예를 들어 아래와 같은 경우다.

//template.h
class NSFinder {
public:
    template <typename T>
    static T getParam(T val);
};

//template.cpp
template <typename T>
T NSFinder::getParam(T val) {
    return val
}

//other program
int main() {
    //에러, 함수를 찾을 수 없다
    int temp = NSFinder::getParam<int>(1);
}

가장 올바른 해결책은 h에 템플릿 코드를 넣는것이다. 하지만 이 방법말고도 가능한 방법이 있다.

1.라이브러리 코드 안에서 컴파일시에 필요한 템플릿 객체 강재로 생성하기.

아래 코드 처럼 템플릿이 존재하는 cpp안에서 필요한 타입의 템플릿 객체를 이용하면, 라이브러리안에 실체가 만들어지기 때문에 링크 에러가 발생하지 않는다. 단점은, 명시적으로 어떤 객체를 사용할지 선언해준 범위에서만 사용가능 하다.

//template.h
class NSFinder {
public:
    NSFinder();
    template <typename T>
    static T getParam(T val);
};

//template.cpp
template <typename T>
T NSFinder::getParam(T val) {
    return val
}

NSFinder::NSFinder() {
    //라이브러리 코드 안에서 한번 사용한다.
    int temp = NSFinder::getParam<int>(1);
}

//other program
int main() {
    //빌드 성공
    int temp = NSFinder::getParam<int>(1);
    //이건 실패한다
    double temp = NSFinder::getParam<double>(1.0);
}

2.템플릿 특수화를 이용해서 만들어준다. 이 방법은 코드가 중복되는 단점과, 명시적으로 어떤 객체를 사용할지 선언해준 범위에서만 사용 가능하다.

//template.h
class NSFinder {
public:
    NSFinder();
    template <typename T>
    static T getParam(T val);
};

//template.cpp
//템플릿 특수화
template <> 
int NSFinder::getParam(int val) {
    return val
}

template <typename T>
T NSFinder::getParam(T val) {
    return val
}

//other program
int main() {
    //빌드 성공
    int temp = NSFinder::getParam<int>(1);
    //이건 실패한다
    double temp = NSFinder::getParam<double>(1.0);
}

여러모로 불편하니, 그냥 해더파일에 템플릿을 구현하는게 정답이다

Advertisements

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

w

%s에 연결하는 중