C++函数模板(Function Template)
这些函数虽然在调用时方便了一些,但从本质上说还是定义了三个功能相同、函数体相同的函数,只是数据的类型不同而已,这看起来有点浪费代码,能不能把它们压缩成一个函数呢?
能!可以借助本节讲的函数模板。
我们知道,数据的值可以通过函数参数传递,在函数定义时数据的值是未知的,只有等到函数调用时接收了实参才能确定其值。这就是值的参数化。
在C++中,数据的类型也可以通过参数来传递,在函数定义时可以不指明具体的数据类型,当发生函数调用时,编译器可以根据传入的实参自动推断数据类型。这就是类型的参数化。
值(Value)和类型(Type)是数据的两个主要特征,它们在C++中都可以被参数化。
所谓函数模板,实际上是建立一个通用函数,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据传入的实参来逆推出真正的类型。这个通用函数就称为函数模板(Function Template)。
在函数模板中,数据的值和类型都被参数化了,发生函数调用时编译器会根据传入的实参来推演形参的值和类型。换个角度说,函数模板除了支持值的参数化,还支持类型的参数化。
一但定义了函数模板,就可以将类型参数用于函数定义和函数声明了。说得直白一点,原来使用 int、float、char 等内置类型的地方,都可以用类型参数来代替。
template<typename T> void printwords(char text[], T arr[4]) {
#ifdef PRINTWORDS
//="asda";
printf("%s\n", text);
if (sizeof(arr[0]) >= 8) {
for (int j = 0; j < 4; ++j) {
printf(" x[%d]=%16llx\n", j, arr[j]);
}
}
else {
for (int j = 0; j < 4; ++j) {
printf(" x[%d]=%9x\n", j, arr[j]);
}
}
#endif
}
void test_printwords() {
u8 a1[4] = { 0x12,0x34,0x56,0x78 };
u16 a2[4] = { 0x1234,0x5678,0xabcd,0xef09 };
u32 a3[4] = { 0x12345678,0xabcd723f,0x01020304,0x05060708 };
u64 a4[4] = { 0x12345678abcd723f,0x0123456789abcdef,0x01020304050607 ,0x08090a0b0c0d0e0f};
printwords((char *)"u8", a1);
printwords((char *)"u16", a2);
printwords((char *)"u32", a3);
printwords((char *)"u64", a4);
}
x00 = U64BIG(*(u64* )(npub));
x01 = U32BIG(*(u32* )(npub + 8));
u32 t0 = U32BIG(((u32*)in)[2]);
u32 t1 = U32BIG(((u32*)in)[1]);
u32 t2 = U32BIG(((u32*)in)[0]);
#include"stdio.h"
void main() {
}
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long long i64;
//#define PRINTSTATE
//#define PRINTWORDS
void printU8(char name[], u8 var[], long len, int offset) {
#ifdef PRINTSTATE
int i,t=256/32;
printf("%s[%d]:\n",name,len);
for(i=0;i<len;i++) {
printf("%02x|",var[i+offset]);
if(i%t==t-1)
printf("\n");
}
printf("\n");
#endif
}
void printwords(char* text, u64 x0, u64 x1, u64 x2, u64 x3) {
#ifdef PRINTWORDS
int i;
printf("%s\n", text);
printf(" x0=%016llx\n", x0);
printf(" x1=%016llx\n", x1);
printf(" x2=%016llx\n", x2);
printf(" x3=%016llx\n", x3);
#endif
}
void printBinaryU8(u8 t) {
int j;
printf("0x%02x : ", t);
for (j = 0; j < 8; j++) {
printf("%d ", t / 0x80);// 下标 ,取最高位
if(j%4==3)printf(" ");
t = t * 2;
}
printf("\n");
}
void getU8Format_1(u8 t) {
//01234567 ->12460000
//& 3 ; << 2; | 2。
u8 t1, t2, t3, t4, t5, t6, t7;
//t = 0xff;
t1 = t & 0xaa;
t2 = t1 << 1;
t3 = t1 | t2;
t4 = t3 & 0xcc;
t5 = t4 << 2;
t6 = t4 | t5;
t7 = t6 & 0xf0;
}
void getU8Format_2_1(u8 in, u8 *out) {
//01234567->02461357
//& 2 ; << 4; ^ 6。
u8 r0, lo = in;
r0 = (lo ^ (lo >> 1)) & 0x22, lo ^= r0 ^ (r0 << 1);
r0 = (lo ^ (lo >> 2)) & 0x0C, lo ^= r0 ^ (r0 << 2);
*out = lo;
}
void printBinary(unsigned char * str, u8 *a, int len) {
printf("%8s:\n", str);
int i, j, count = 0;
u8 t;
for (i = 0; i < len; i++) {
t = a[i];
printf("0x%02x : ", t);
for (j = 0; j < 8; j++) {
printf("[%2d]%d ", (len - 1 - i) * 8 + j, t / 0x80);// 下标 ,取最高位
t = t * 2;
}
printf("\n");
}
printf("\n");
}
void printBinarySimp(unsigned char * str, u8 *a, int len) {
printf("%8s[%d]:", str, len);
int i, j, count = 0;
u8 t;
for (i = 0; i <len; i++) {
printf("%02x", a[i]);// 下标 ,取最高位
if((i)%8==7)
printf(" ");
}
printf("\n");
for (i = 0; i <len; i++) {
t = a[i];
// printf("0x%02x : ", t);
for (j = 0; j < 8; j++) {
printf("%d", t / 0x80);// 下标 ,取最高位
t = t * 2;
}
printf(" ");
}
printf("\n");
}