2009-11-25 134 views
9

我想專門類模板具有以下功能:模板專業化與模板化類型

template <typename T> 
class Foo 
{ 
public: 
    static int bar(); 
}; 

功能沒有參數,並應返回基於美孚類型的結果。 (在這個玩具例子中,我們返回類型的字節數,但在實際應用中,我們想返回一些元數據對象。) 專業化工程完全指定類型:

// specialization 1: works 
template <> 
int Foo<int>::bar() { return 4; } 

// specialization 2: works 
template <> 
int Foo<double>::bar() { return 8; } 

// specialization 3: works 
typedef pair<int, int> IntPair; 
template <> 
int Foo<IntPair>::bar() { return 2 * Foo<int>::bar(); } 

然而,我想把它推廣到依賴(其他)模板參數本身的類型。 添加以下專業化給出了一個編譯時錯誤(VS2005):

// specialization 4: ERROR! 
template <> 
template <typename U, typename V> 
int Foo<std::pair<U, V> >::bar() { return Foo<U>::bar() + Foo<V>::bar(); } 

我假定這是不合法的C++,但是爲什麼呢?有沒有一種方法來優雅地實現這種模式?

+1

但是請注意,你不需要任何特殊化返回T的大小:'static int Foo(){return sizeof(T); }'。我想知道這種模式可能無助於你的真正問題。 – UncleBens 2009-11-25 15:28:06

回答

7

Partitial專業化只爲類,而不是功能是有效的。

解決方法:

template <typename U, typename V> 
class Foo<std::pair<U, V> > { 
public: 
static int bar() { return Foo<U>::bar() + Foo<V>::bar(); } 
}; 

如果您不希望完全專注類,使用輔助結構

template<class T> 
struct aux { 
    static int bar(); 
}; 

template <>int aux <int>::bar() { return 4; } 
template <>int aux <double>::bar() { return 8; } 

template <typename U, typename V> 
struct aux <std::pair<U, V> > { 
    static int bar() { return Foo<U>::bar() + Foo<V>::bar(); } 
}; 

template<class T> 
class Foo : aux<T> { 
    // ... 
}; 
+1

在這個例子中,所有的專業化是專業化的 – TimW 2009-11-25 15:10:07

+1

是的。對。功能partitial specialize是禁止的。僅可以爲功能欄創建基類。 – 2009-11-25 15:14:50

+0

@TimW,在這個問題中,訣竅是該類不是專門的。這不符合標準:「類模板的成員函數,成員類或靜態數據成員可能明確專用於隱式實例化的類專用化;如果類模板名稱成員的顯式專用化一個隱含聲明的特殊成員函數(第12條),該程序不合格。「這是針對該模板的一個給定隱式實例化(因此沒有模板參數依賴性)的專門化(不適用於任何部分專業化)。 – 2009-11-25 15:16:54

5

它在C++中是完全合法的,它是部分模板專業化。
取出template <>,如果它不已經存在添加明確的類模板專業化,它應該編譯在VS2005(但不是在VC6)

// explicit class template specialization 
template <typename U, typename V> 
class Foo<std::pair<U, V> > 
{ 
public: 
    static int bar(); 
}; 

template <typename U, typename V> 
int Foo<std::pair<U, V> >::bar() { return Foo<U>::bar() + Foo<V>::bar(); } 
+1

@litb據我所見,他所有的功能都是階級專業化。我沒有看到任何函數模板,是嗎? – TimW 2009-11-25 15:14:47

+0

@TimW:當你聲明一個類模板時,每個成員函數都是一個獨立的函數模板。 OP正在嘗試專門化一個成員函數模板而不專門研究整個類模板。這纔是重點。但是,函數模板不支持部分特化。那就是問題所在。 – AnT 2009-11-25 15:23:46

+0

@TimW,沒有函數模板。但是也沒有明確的類模板專業化。請參閱上面的標準引用:這是標準中的一種特殊情況,它允許明確地專門化類模板的單獨非模板成員,而不明確地專門化它們的整個類模板。它通過命名一個給定的隱式實例(在他的例子中,例如'Foo '或'Foo '),在沒有任何'Foo'的任何部分專精的情況下,將選擇主要模板並專門化其'bar'成員。 – 2009-11-25 15:24:09