2011-11-19 4 views
1

저는 템플릿 기반 클래스의 멤버 함수에 대해 여러 가지 다른 함수 정의를 갖고 싶습니다. 이런 식으로 :템플릿 멤버 함수를 특수화 하시겠습니까?

위와 같이 구현해 보았고 명시 적으로 인스턴스화하려고하는 모든 특수 유형에 대해 링커 오류가 발생했습니다. 링커 오류는 함수가 이미 이전에 정의되었음을 나타냅니다. 어쩌면 내가 잘못된 장소에서 찾고 있어요하지만 난 나에게이 문제 :(그렇다면

Q.이 가능합니까?,이 작업을 수행하고 어떻게 왜 작동 하는가를 파악하기 위해 모든 자원을 찾을 수 없습니다?

감사합니다!

+0

난 그냥 두 개의 서로 다른 소스 파일에서 포함 된 헤더 파일에 정의를 붙여; 두 소스 파일에서 특수 및 비 특화 템플릿 클래스의 인스턴스 모두에 대해 Foo() 메서드를 호출했습니다. 모든 것은 g ++로 잘 작동합니다 - 4.4.3. 정확한 링커 오류와 프로젝트의 구조에 대해 좀 더 자세히 설명해 주시겠습니까? – misberner

+1

이렇게하면됩니다. 당신의 문제는 다른 곳에 있어야합니다. 일반적인 템플릿 메커니즘과 헤더 및 링크 문제에 익숙해야합니다. –

+1

[나를위한 작품] (https://ideone.com/IpHd0). –

답변

3

다음은 자주 사용하는 문제 해결 방법입니다. 전에 말했듯이 전체 템플릿을 전문화해야합니다. 아이디어는 구조체의 정적 멤버를 특수화하려는 메서드를 만드는 것입니다 (캡슐화 이유로 중첩 및 비공식이어야 함).이 같은 주에 지금

template< typename T > 
class MyClass { 

    struct PerformFoo { 
     static void doFoo() { 
      std::cout << "Foo for general type" << std::endl;; 
     } 
    }; 

public: 
    void Foo() { 
     PerformFoo::doFoo(); 
    } 
}; 

template<> 
struct MyClass<float>::PerformFoo { 
    static void doFoo() { 
     std::cout << "Foo for float" << std::endl;; 
    } 
}; 

, 코드

MyClass<int> myInt; 
myInt.Foo(); 

MyClass<float> myFloat; 
myFloat.Foo(); 

인쇄 터미널에

Foo for general type 
Foo for float 

. 그건 그렇고 현대 컴파일러에서는 성능상의 불이익이 없다. 희망이 당신을 도와줍니다.

+0

감사합니다.이 문제는 확실히 해결됩니다. 그래서이 함수가 작동하는 이유는 사용하기 전에 함수 호출을 완전히 전문화해야하기 때문입니다. 그리고 내 클래스가 특수화 할 수있는 구조체의 정적 멤버로 만들어줌으로써 구조체 자체가 전문화 될 것이라는 확신을 갖게됩니다. 도움에 다시 한번 감사드립니다. – KiraBox

+0

지연된 답변을 드려 죄송합니다. C++ 컴파일러 구현 전문가가 아니기 때문에 이것이 '올바른'설명인지는 모르겠습니다. 나는 단지 이것이 작동한다는 것을 알고 있으며,이 트릭은 과학 프로젝트에서 사용되어 많은 다른 사람들과 함께 작업하고 있습니다 :) – Sh4pe

-1

그것은 불가능합니다. 템플릿을 전문으로 할 때,이 경우 전체 클래스를 의미한다 전체 템플릿을 전문으로한다.

당신은 foo는 내부 템플릿 기능을 할 수 있습니다 템플릿 클래스. 요구하는 것과 정확히 일치하지는 않지만 요구 사항을 충족 할 수 있습니다.

는 업데이트 :

template<typename T> class Foo { 
public: 
    template<typename R> void foo() {printf("This is foo\n");} 
    template<> void foo<float>() {printf("This is foo<float>\n");} 
}; 

또는 :

template<typename T> class Foo { 
public: 
    template<typename R> void foo() {printf("This is foo\n");} 
    //template<> void foo<float>() {printf("This is foo<float>\n");} 
}; 

template<> template<> void Foo<float>::foo<float>() { 
    printf("This is foo<float>\n"); 
} 

과 함께 :

int main(int argc,char * argv[]) 
{ 
    Foo<int> iFoo; 
    iFoo.foo<int>(); 

    Foo<float> fFoo; 
    fFoo.foo<float>(); 

    return 0; 
} 

를 생성 :

This is foo 
This is foo<float> 
,536,

foo을 호출하는 구문은 다소 어색합니다.

+0

나는 똑같은 생각을했지만, 간단한 실험 (g ++ 4.4.3 사용)은 나에게 틀린 것으로 판명되었다. – misberner

0

위와 같이 구현해 보았습니다. 명시 적으로 인스턴스화하려고 시도하는 모든 특수 유형에 대해 링커 오류가 발생했습니다.

그 의미는 무엇입니까? 명시 적으로 템플릿을 전문화하면 동일한 템플릿 인수에 대해 명시 적으로 인스턴스를 생성 할 수 없습니다. 명시 적 전문화의 전체 목적은 당신의 명시 적 전문성 찬성 (A 생성 전문화이다) 그것의 인스턴스를 방지하는 것입니다.

그래서 설명을 나에게 이해가되지 않습니다. 암시 적으로 인스턴스화하려는 경우 .cpp 파일 대신 헤더에 템플릿 및 클래스 템플릿의 멤버 함수 정의를 넣어야한다는 점을 기억하십시오. 그리고 명시적인 특수화는 템플릿을 인수로 사용하는 모든 사람에게 선언해야합니다.

// put this specialization into the header, for everyone to see 
template <> void MyClass<float>::Foo(); 
1

특수 멤버 함수를 인라인 함수로 정의하면 특정 멤버 함수가 다른 곳에서 정의되었다고 불평하는 링크 오류가 제거됩니다.

//handles a special type in a different way 
template <> 
inline void 
MyClass<float>::Foo() 
{ 
    return val + 5.0f; 
} 

특수화 된 기능이 더 이상 기능 템플릿이 아니라 구체적인 기능이라는 이유 때문입니다. 따라서이 헤더 파일을 포함하는 소스 파일을 컴파일 할 때 여러 번 컴파일되므로 "이미 정의 된"오류가 발생합니다.

또 다른 해결책은 특수 기능의 구현을 헤더 파일 밖으로 옮기고 소스 파일에 넣는 한편 헤더 파일에 특수 기능을 선언하는 것입니다. 전문 멤버 함수의 선언은 클래스 정의 외부에서 유지해야합니다 :

/// Declare the specialized function in the header file but outside the 
/// class definition. 
template <> void MyClass<float>::Foo() 

/// Define the specialized function in .cpp file: 
template <> 
void 
MyClass<float>::Foo() 
{ 
    return val + 5.0f; 
} 
관련 문제