문제

C++ 템플릿과 관련하여 어떤 일이 벌어지고 있는지 거의 모르지만 주어진 속성을 만족하는 요소에 대한 벡터를 검색하는 함수를 구현하려고 합니다(이 경우에는 주어진 이름을 가진 요소 검색).내 .h 파일의 선언은 다음과 같습니다.

template <typename T>
T* find_name(std::vector<T*> v, std::string name);

컴파일할 때 함수를 호출하면 다음 링커 오류가 발생합니다.

Error   1   error LNK2019: unresolved external symbol "class Item * __cdecl find_name<class Item>(class std::vector<class Item *,class std::allocator<class Item *> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??$find_name@VItem@@@@YAPAVItem@@V?$vector@PAVItem@@V?$allocator@PAVItem@@@std@@@std@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z) referenced in function "public: class Item * __thiscall Place::get_item(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?get_item@Place@@QAEPAVItem@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) place.obj   Program2

다시 말하지만, 저는 템플릿을 처음 접했기 때문에 무슨 일이 일어날지 모릅니다.Google을 통해 LNK2019에서 찾은 모든 사례는 올바른 라이브러리를 사용하지 않은 것에 관한 것이지만 이것이 내 기능이므로 왜 이런 일이 발생하는지 알 수 없습니다.

또한 관련 질문은 다음과 같습니다.특정 클래스의 하위 클래스가 되도록 템플릿 매개변수를 만드는 방법이 있습니까?주형?

도움이 되었습니까?

해결책

호출 사이트에서 템플릿 정의를 사용할 수 있어야 합니다.그건 아니란 뜻이야 .cpp 파일.

그 이유는 템플릿을 컴파일할 수 없기 때문입니다.함수를 쿠키로 생각하면 컴파일러는 오븐입니다.

템플릿은 쿠키의 유형을 모르기 때문에 쿠키 커터일 뿐입니다.이는 유형이 주어졌을 때 컴파일러에게 함수를 만드는 방법을 알려주지만, 그 자체로는 작동되는 구체적인 유형이 없기 때문에 사용할 수 없습니다.쿠키 커터를 요리할 수는 없습니다.맛있는 쿠키 반죽이 준비된 경우에만(즉, 컴파일러에 반죽 [유형] 제공) 쿠키를 자르고 요리할 수 있습니다.

마찬가지로 특정 유형의 템플릿을 실제로 사용할 때만 컴파일러가 실제 함수를 생성하고 컴파일할 수 있습니다.그러나 템플릿 정의가 누락된 경우에는 이 작업을 수행할 수 없습니다.이를 헤더 파일로 옮겨야 함수 호출자가 쿠키를 만들 수 있습니다.

다른 팁

당신은 아마도 유효한 인스턴스화를 놓치고있을 것입니다. 템플릿 정의를 별도의 .CPP 파일에 넣으면 컴파일러가 해당 파일을 컴파일하면 필요한 인스턴스를 알지 못할 수 있습니다. 반대로, 올바른 버전의 템플릿 함수를 인스턴스화하는 통화 사이트에서 기능 본문의 정의를 사용할 수없는 경우 컴파일러에는 필요한 전문화를 인스턴스화 할 정보가 없습니다.

두 가지 옵션이 있습니다. 기능 템플릿의 기능 본문을 헤더 파일에 넣습니다.

예 : 헤더 파일의 :

template <typename T>
inline T* find_name(std::vector<T*> v, std::string name)
{
    // ...
}

또는 템플릿을 정의한 .cpp의 템플릿을 명시 적으로 인스턴스화합니다.

예를 들어 소스 파일에 있습니다 (아마도 필요할 것입니다 #include정의하는 파일을 ing Item):

template <typename T>
T* find_name(std::vector<T*> v, std::string name)
{
    // ...
}

template Item* find_name<Item>(std::vector<Item*> v, std::string name);

여기의 답은 훌륭합니다.

나는 이것이 종종 그 이유입니다. .h 그리고 .cpp 프로젝트의 파일. 당신은 종종 찾을 수 있습니다 .inl 파일. 템플릿 정의가로 들어갑니다 .inl 파일.

이것들 .inl 파일은 인라인을 의미하며 일반적으로 .h 모든 헤더 선언 후 파일 하단에서 동일한 이름 접두사 파일. 이것은 효과적으로 헤더 파일의 일부를 만들지 만 선언을 모든 정의와 분리합니다.

영광의 헤더 파일이기 때문에 일반 헤더 파일 (예 : 가드 등)과 동일한 예방 조치를 취해야합니다.

같은 문제를 발견하고 이것을 발견 한 3 개의 해결 방법을 발견했습니다.http://www.codeproject.com/articles/48575/how-to-define-a-template-in-ah-file-and-imp

그중에는 .cpp 파일에서 "더미"메소드를 생성하는 쉬운 것이 있으며, 다른 유형으로 템플릿/클래스 함수를 호출합니다. 링크에서 붙여 넣기 :

// No need to call this TemporaryFunction() function, it's just to avoid link error.
void TemporaryFunction ()
{
    TestTemp<int> TempObj;
    TestTemp<float> TempObj2;
}

방금 당신이 답이없는 것처럼 보이는 두 번째 질문이 있음을 알았습니다.

템플릿 매개 변수를 만들어 특정 클래스, 즉 템플릿의 서브 클래스가되어야합니까?

것이 가능하다. 예를 들어, 참조하십시오 is_base_of 안에 boost.typetraits.

그러나 나는 궁금합니다. 왜 그것을 원하십니까? 일반적으로 매개 변수에 대한 템플릿의 요구 사항은 매개 변수 유형 자체가 아니라 해당 유형과 관련된 표현이 합법적입니다. 예를 들어, 당신이 가지고 있다고 상상해보십시오.

template<class T>
void foo(const T& t)
{
    if (t.foo()){
       t.bar("blah");
    }
}

t는 다음과 같은 것에서 물려 받아야한다고 말합니다.

class HasFooAndBar
{
public:
  void foo()const;
  void bar(const char*)const;
};

유형이 작업을 지원하지 않으면 함수의 인스턴스화가 실패하기 때문에 아무것도 가져 오지 않습니다. 또한, 그것은 적용 가능성을 불필요하게 제한합니다 foo(). 사실, Foo의 모든 요구 사항은 바로 그 것입니다 t.foo() and t.bar(const char*) 예를 들어,이 유형은 Hasfooandbar에서 상속되지 않으며 여전히 유효한 foo () 매개 변수입니다.

struct DifferentFromHasFooAndBar
{
  bool foo()const;
  std::string bar(const std::string&)const;
};

템플릿 기능 정의를 CPP 파일에 넣었습니까? 그런 다음 헤더로 이동하여 인라인으로 이동하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top