2014-09-13 64 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