2013-07-30 3 views
2

템플릿 함수 (이 경우 정적 메서드로 클래스에 있음)를 만들려고하는데 템플릿을 호출 할 수 없습니다. 내가 만든 사양. 즉, 내가 만든 템플릿 스펙을 코드가 호출 할 것으로 예상했으나 그렇지 않습니다.가변 변수가있는 템플릿 함수 - 템플릿 특수화를 호출 할 수 없습니다.

class Atomic { 
public:  
    template <typename T> 
    static T testAndSet(volatile T &t, T value) 
    { 
     ASSERT(false, "Unsupported type"); 
     return T(); 
    }; 

    template <long> 
    static long testAndSet(volatile long &t, long value) 
    { 
    #if defined(_PC) 
     return InterlockedExchange(&t, value); 
    #else 
     return __sync_lock_test_and_set(&t, value); 
    #endif 
    }; 
}; 

국가 번호 :

volatile long counter = 0;  
long newValue = 4; 
Atomic::testAndSet(counter, newValue); 

호출 스택을 보여줍니다!

SAMPLE.EXE 원자 :: 검사와 지정 (휘발성 긴 & t = 0, long 값 = 4)

나는 또한이 방법을 시도했지만 작동하지 않았다.

template <typename T, typename TT> 
static TT testAndSet(T &t, TT value) { ... } 

template <volatile long, long> 
static long testAndSet(volatile long &t, long value) { ... } 

또는

template <typename T, typename TT> 
static TT testAndSet(T t, TT value) { ... } 

template <volatile long &, long> 
static long testAndSet(volatile long &t, long value) { ... } 

똑같은

는 ... 그래서 지금은 시도하고 대신 happenning이나 짐승이 그것으로 내 방식을 강요 무슨 이해해야한다. 그때까지는 Lavavej의 핵심 C++ 비디오를 시청할 것입니다. =)

답변

2

명시 적으로 템플릿 함수를 특수화 할 수는 있지만 함수의 표준 방법은 아닙니다. 그리고 여러분이 할 수있는 것처럼 할 수는 없습니다 : 여러분이 쓴 것은 두 개의 템플릿 함수입니다. 하나는 형식 매개 변수이고 다른 하나는 long 비 유형 매개 변수입니다.

// This defines a template function parameted with a long 
// vvvvvvvvvvvvvvv 
    template <long> 
    static long testAndSet(volatile long &t, long value) 

당신은이 컴파일러에 의해 수행되지 않았다 그 이유는,이 과부하가 고려되어야하는 전화 사이트에 명시 적으로 템플릿 매개 변수를 지정해야합니다. 당신은 여기에 과부하가 필요

는 (명시 적 전문성이 필요하지 않은)이 하나 이전의 기능을 변경 :

// Not a template function 
    static long testAndSet(volatile long &t, long value) 

을 또한, 기능 템플릿을 전문 클래스보다 같은 구문을 사용하여 수행됩니다

// Base case 
template<typename T> 
void function(T value); 

// Explicit specialization (just an example) 
template<> 
void function<int>(int v, int a); 

명시 적 특수화와 단순 과부하 간에는 몇 가지 차이점이 있습니다. 자세한 내용은 this SO question을 참조하십시오.

+0

네 말이 맞아! 나는 처음에는이 방법을 사용했으나 GCC 용으로 컴파일하려고 시도했을 때 수정되었다. (어떤 경우 든 다른 질문이다. 그래서 여기에 물어 보지 않을 것이다. (이름 공간이 아닌 scope 클래스 Atomic의 명시적인 전문화와 관련이있다). 전문화 때문에 여러 유형을 전문으로하고 싶었지만 모두 (연동은 OS에 따라 다른 유형을 지원합니다.) 오버로드로 전환하는 것을 고려해 볼 것입니다. Tks 많이! – MasterPlanMan

1
template <long> 
static long testAndSet(volatile long &t, long value) 
{ 
#if defined(_PC) 
    return InterlockedExchange(&t, value); 
#else 
    return __sync_lock_test_and_set(&t, value); 
#endif 
}; 

그건 당신이 생각하는 것처럼 전문화되지 않았습니다. 이것은 (이름이없는) non-type 템플릿 매개 변수로 오버로드됩니다. 명시 적으로 매개 변수를 지정해야하기 때문에 사용자가 작성한 호출에 대해 과부하 해결 중에 선택되지 않습니다 (예 : testAndSet<42>(counter, newValue);).

template <> // <--- 
static long testAndSet<long>(volatile long &t, long value) 
{     // ^^^^^^ 
    //.... 
} 

하지만 그 시점에서 당신은뿐만 아니라 정상적인 과부하를 제공 할 수있다 :

당신이 원하는 구문입니다.

기능 템플릿 특수화 can surprise you 때문에 항상 오버로드를 선호해야합니다.

+0

당신은 둘 다 똑같은 대답을 가지고 있습니다. 나는 대답을 1 개만 선택해서 답변에 첫 번째 태그를 지정할 것입니다 (1 분 차이!). 당신의 도움을 많이 Tks! – MasterPlanMan

+0

@ user1459231 땀, 친구. (그러나 나는 먼저 대답했다 : D) – jrok

관련 문제