2013-04-10 7 views
3

템플릿 기능이 다른 템플릿 기능을 상속하는 설치가 있습니다.템플릿 기능의 재 선언 오류

template <typename DataType> 
class ClassBase 
{ 
    virtual void InitModel(const cv::Mat& data) {}; 
} 

template <typename DataType> 
class ClassDerived : public ClassBase<DataType> 
{ 
    void InitModel(const cv::Mat& data) {}; 
} 

지금 내가 쓴 전에, 내가 어떤 전문화를 가지고 있지 않았고 그것을 잘 작동했다

template<> 
void ClassDerived<float>::InitModel(const cv::Mat& data) 
{ 
// initialize some things 
} 

template<> 
void ClassDervied<cv::Vec3b>::InitModel(const cv::Mat& data) 
{ 
    // initialize some things 
} 

template<typename DataType> 
void ClassDerived<DataType>::InitModel(const cv::Mat& data) 
{ 
    // initialize some things 
} 

구현 파일에 두 개의 전문과 ClassDerived에 InitModel로 하나 일반적으로 템플릿을 구현하려고합니다. 특수화 기능을 추가하자마자 스펙 기능을 다시 선언했음을 알리는 오류가 발생합니다. 이상한 부분은 재 선언이 같은 행 번호를 가리킨다는 것입니다. 동일한 파일에 있습니다. 특수화되기 전에 정상적으로 작동 했으므로 파일을 두 번 읽지 않을 것으로 예상됩니다.

그래서 특수화가 추가되는 즉시 왜 그런 오류가 나타나기 시작합니까?

오류 :

/other/workspace/perception/perception_kit/object_detection/include/perception_kit/object_detection/grimson_GMM_templated_impl.tpp:129 : 의 여러 정의`perception_kit :: GrimsonGMMGen :: InitModel로 (CV : 매트 const를 &) ' CMakeFiles/test_obj.dir/SRC/object_detection_templated_test_platform.cpp.o : /other/workspace/perception/perception_kit/object_detection/include/perception_kit/object_detection/grimson_GMM_templated_impl.tpp : 129 : 먼저 정의를 여기

템플릿 기반 클래스 또는 다른 것을 파생하려고하기 때문에 문제가 있습니까?

나는 그것이 사소한 문제 일지 모르지만 나는 여기에 게시하기 전에 상당한 시간을 보냈다.

베이스 클래스 BaseClass.h (그것의 추상 클래스로서 구현) 파생 클래스 선언 DerivedClass.h 에 인 파생 클래스 선언 DerivedClass.tpp이고

+0

이 ClassDerived <떠 :: InitModel로'에서 누락 된 꺾쇠 괄호가 '오타가?(btw, 명시 적 전문화가 아니면 클래스 템플릿의 멤버 함수 정의가 헤더 파일에 속해야합니다.) –

+0

템플릿 정의 및 구현을 두 개의 다른 파일로 분할합니까? – andre

+0

네, 이건 쓸 것이 많았습니다. 오타입니다. 정의는 .h이며 선언은 .hpp에 포함 된 .tpp에 있습니다. – navderm

답변

1

이 있으시면에 해당 유형의 전문 분야가 있음을 선언해야합니다. 그렇지 않으면 다른 번역 단위의 컴파일러가 템플릿을 인스턴스화하면 기본 템플릿을 기반으로하는 멤버 함수에 대한 코드가 생성됩니다. 생성 된 함수를 특수화와 연결하려고하면 링커에서 특수화에 대한 여러 정의가 표시됩니다.

// Header 
template <typename T> 
struct test { 
    void f() {} 
}; 
template <> 
void test<int>::f();  // Declare the specialization 

// Implementation (cpp, not included by client code) 
template <> 
void test<int>::f() { ... } 

함수 특수화는 더 이상 템플릿이 아니라 일반 함수입니다. 다른 번역 단위에 함수 정의가 포함되어 있으면 여러 번역 단위로 코드가 생성됩니다. 당신이하고 싶은 경우에, 당신은 전문화의 선언을 건너 뛸 수 있습니다 직접 정의를 제공,하지만 당신은 그것을 inline을해야합니다 :

// Implementation (if in header/included by user code) 
template <> 
inline void test<int>::f() { ... } 
+0

나는 여전히 같은 오류가 발생합니다. – navderm

+0

@navderm : 잠깐 기다려주세요. 구현 파일은 .cpp입니까? 아니면 여러 번역 단위에서 포함 시키시겠습니까? 완벽한 전문화 (전문화의 유일한 형태 인 기능의 경우)는 더 이상 템플릿이 아니라 정규 기능입니다. 헤더에 살기를 원하면 해당 전문화를 '인라인'으로 만들어야합니다. 답변을 업데이트했습니다. –

+0

현재 특수화는 .h 파일에 포함 된 .tpp 파일에 있습니다. – navderm

2
DerivedClass.h에 포함

헤더 (빈 본문 포함)에 기본 템플릿 코드 인라인이 이미 정의되어 있으므로 나중에 다시 정의 할 수 없습니다. 그게 전문 분야가 아니라 여기가 당신 문제의 근원이라고 생각합니다.

+0

죄송합니다. 가상 키워드를 추가했습니다. 가상 기능을 사용한다고해도 사실입니까? – navderm

+0

@navderm :'virtual' 키워드는 여기서는 아무런 영향을 미치지 않습니다. 템플릿의 각 인스턴스화시 멤버 함수를 인스턴스화해야합니다 (가상 함수는 항상 * odr-used *이므로). 문제에 영향을 미칩니다. 컴파일러는 템플릿을 수동으로 전문적으로 사용한다는 것을 모르기 때문에 템플릿 정의에서 특수화를 생성합니다. –