2014-09-13 59 views
0

我希望有一組函數可以接受任何uintX_t變體,而無需複製/粘貼大量代碼。到目前爲止,我正試圖使用​​「標記」來確定要調用的函數。由於顯而易見的原因,T = unsigned不起作用,因爲我可能有uint32_tuint16_t用於顯式功能專業化的默認模板參數

struct number_tag {}; 
struct hexadecimal : number_tag {}; 
struct number : number_tag {}; 

template <typename T = unsigned, typename Tag> 
void write(T t); 

再後來在.cpp文件:

template <> 
void write<unsigned, hexadecimal>(unsigned num) 
{ 
} 

template <> 
void write<unsigned, number>(unsigned num) 
{ 
} 

,理想我想這樣稱呼它:

write<number>(10); 
write("\n"); 
write<hexadecimal>(0xFF); 

如何我寫這篇文章,這樣我就不用做write<unsigned, number>和創建一批專業化的每一個uintX_t變種?

+2

注意這樣的代碼'寫 (10);'暗示'number'是* first *模板參數,這就是爲什麼兩個答案都顛倒了模板參數的順序。 – aschepler 2014-09-13 12:45:05

回答

3

你不能部分專門化功能(噓),但你可以做更多無用的結構!

struct number_tag {}; 
struct hexadecimal : number_tag {}; 
struct number : number_tag {}; 

template <typename Tag, typename T = unsigned> 
struct Writer; 

template <typename T> 
struct Writer<hexadecimal, T> 
{ 
    static void write(T num) {} 
}; 

template <typename T> 
struct Writer<number, T> 
{ 
    static void write(T num) {} 
}; 

template <typename Tag, typename T = unsigned> 
void write(T t) 
{ 
    Writer<Tag, T>::write(t); 
} 

int main() 
{ 
    write<number>(10); 
    write<hexadecimal>(0xFF); 
} 
+0

您可能需要在實現中的某處使用'typename std :: make_unsigned :: type',具體取決於您想要對負輸入做什麼。 – aschepler 2014-09-13 12:49:20

1

如果你想使用一個單獨的write專業化取決於tag,再加入重載(因爲功能不能部分專用):

template <typename T = unsigned> 
void write(T t, hexadecimal tag) 
{ 
} 

template <typename T = unsigned> 
void write(T t, number tag) 
{ 
} 

template <typename Tag, typename U = unsigned> 
void write(U num) 
{ 
    write<U>(num, Tag{}); 
} 

write<number>(10); 

write<hexadecimal>(0xFF); 

write<number, std::uint16_t>(0xFF); 

DEMO


如果您想爲你的函數添加一個約束,以便它只接受無符號的種整數類型,下面的代碼做了正確的驗證:

template <typename Tag, typename U = unsigned> 
auto write(U num) -> typename std::enable_if<std::is_unsigned<U>::value, void>::type 
{ 
    write<U>(num, Tag{}); 
} 

write<number>(10u); 

//write<number>(-1); // triggers error 

DEMO 2

注:當前的聲明template <typename T = unsigned> void write(T t);不會強制類型爲unsigned,因爲一個參數的類型是由編譯器根據實際參數的類型推導出來。


如果要強制傳遞給write功能的任何類型的unsigned,你可以使用下面的代碼:

template <typename Tag, typename U> 
void write(U num) 
{ 
    write<typename std::make_unsigned<U>::type>(num, Tag{}); 
} 

write<number>(-1); // gets converted to unsigned type 

DEMO 3

+0

對於'std :: enable_if'爲+1 – P0W 2014-09-13 12:53:31