2016-05-30 67 views
1

局部模板類專業化的以下基本示例中,從this wiki page採取:模板類部分特例語法

template <typename Key, typename Value> 
class KeyValuePair { /* something generic */ }; 

template <typename Key> 
class KeyValuePair<Key, bool> { /* something specific to Value=bool */ }; 

KeyValuePair<int> kvpi; 

生成編譯器錯誤:

prog.cpp:10:17: error: wrong number of template arguments (1, should be 2) KeyValuePair<int> kvpi; 

爲什麼呢?我究竟做錯了什麼 ? 應該如何聲明和實例化部分模板類專業化?

我期待變量kvpiKeyValuePair<int,bool>類型的部分專用模板類實例。

+0

你有什麼期望'Value'在'KeyValuePair '? – TartanLlama

+0

@TartanLlama:在'KeyValuePair '中,我期望'Value'是'bool',但我沒有明確地定義部分特殊化來正確地這樣做。 – shrike

+2

@shrike部分專業化並不按照您期望的方式工作。您將不得不提供密鑰和值類型。只有當值類型爲bool時,它纔會選擇專門的類實現,對於所有其他類型,它將使用第一個實現。 – Arunmu

回答

3

你似乎有混淆局部特殊化默認模板參數。它進一步顯示你需要兩個(由於未說明的原因,但不是很重要)。雖然不是完全直觀的,它可以如下完成:

#include <iostream> 

template <typename Key, typename Value = bool> 
class KeyValuePair 
{ 
public: 
    KeyValuePair() 
    { 
     std::cout << __PRETTY_FUNCTION__ << ':' << "original\n"; 
    } 
}; 

template <typename Key> 
class KeyValuePair<Key, bool> 
{ 
public: 
    KeyValuePair() 
    { 
     std::cout << __PRETTY_FUNCTION__ << ':' << "specialized\n"; 
    } 
}; 


int main() 
{ 
    KeyValuePair<int,int> kvp1; 
    KeyValuePair<int> kvp2; 
} 

輸出

KeyValuePair<int, int>::KeyValuePair() [Key = int, Value = int]:original 
KeyValuePair<int, bool>::KeyValuePair() [Key = int, Value = bool]:specialized 

混亂的部分,有些是默認的參數規格,但模板下面,將永遠不會真正看到由於後來的專業化,因此與默認參數相結合。在這種情況下,我更願意使用其默認參數列表轉發聲明該模板。至少對我來說,它使讀起來更容易一些。如果您覺得它清晰明瞭,您可以(或不)選擇這樣做。例如:

template <typename Key, typename Value = bool> 
class KeyValuePair; 

template <typename Key, typename Value> 
class KeyValuePair 
{ 
public: 
    KeyValuePair() 
    { 
     std::cout << __PRETTY_FUNCTION__ << ':' << "original\n"; 
    } 
}; 

template <typename Key> 
class KeyValuePair<Key, bool> 
{ 
public: 
    KeyValuePair() 
    { 
     std::cout << __PRETTY_FUNCTION__ << ':' << "specialized\n"; 
    } 
}; 
+0

我確實混淆了部分專業化和默認參數化;而且我實際上需要兩個,就像你的片段說明一樣。感謝您的回答。 – shrike

2

您可以正確定義您的部分專業化,但模板需要2個參數,並且您只提供一個參數。

你可以使用默認參數:

template <typename Key, typename Value = bool> 
class KeyValuePair {}; 

允許

KeyValuePair<int> kvpi; 

你可以保留你的局部特殊化如果需要

template <typename Key> 
class KeyValuePair<Key, bool> { /* something specific to Value=bool */ }; 
+0

好吧,明白了,我混淆了部分專業化和默認參數;實際上,我需要兩個。感謝您指出什麼是錯誤的。 – shrike

+0

@ Jarod42:謝謝你的回答,我確實需要一個默認參數,但我也需要一個部分專門化(例如:KeyValuePair的實現在使用參數Key僅實例化時必須不同);將其添加到您的代碼段,我接受你的答案。 – shrike

3

部分模板專門化不允許您忘記模板參數。你必須寫:

KeyValuePair<int, bool> kvpib; 

和正確的專業化將被使用。

但是你可以使用繼承來實現你想要的:

template <typename Key> 
class KeyBoolPair : public KeyValuePair<Key, bool> {}; 

KeyBoolPair<int> kbpi; 

,或者如果您使用C++ 11或更高:

template <typename Key> 
using KeyBoolPairBis = KeyValuePair<Key, bool>; 

KeyBoolPairBis<int> kbpbi; 

例如:http://coliru.stacked-crooked.com/a/5095fc5c358d291a

+0

接縫也可以滿足我的需求;這將等同於使用部分專業化與默認參數(如來自WhozCraig的答案)? – shrike

+0

對我來說,這不是等同的:開發人員不能確定不使用'KeyValuePair'只有一個模板參數;他們必須使用「另一個」類。這另一個類是基於(繼承)或'KeyValuePair'的別名('using'關鍵字)。並且在這兩種情況下,您都必須使用專門的模板(即,使用'template class KeyValuePair ....')。 Personnaly,我更喜歡'使用' – Garf365

+0

好吧,我沒有注意到你改變了模板類的名字,這確實是強制性的;那麼使用默認參數的解決方案將最適合我的需求,因爲名稱不會更改。不管怎樣,謝謝。 – shrike