2023/9/9
模板函数,实例化&具体化
编译器对函数的优先选择
#include <iostream>
using namespace std;
typedef struct Job
{
char name[40];
double salary;
int floor;
} job;
template <typename T>
void Swap(T &a, T &b);
template <>
void Swap<job>(job &j1, job &j2);
void show(job &j);
int main()
{
int i = 10, j = 20;
cout << "i, j = " << i << " , " << j << ".\n";
cout << "Using compiler generated ubt swapper:\n";
Swap(i, j);
cout << "Now i, j = " << i << " , " << j << ".\n";
job mizuki = {"mizuki", 114514, 1};
job mostima = {"mostima", 1919810, 4};
show(mizuki);
show(mostima);
Swap(mizuki, mostima);
cout << "after:\n";
show(mizuki);
show(mostima);
return 0;
}
template <typename T>
void Swap(T &a, T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
template <>
void Swap<job>(job &j1, job &j2)
{
double t1;
int t2;
t1 = j1.salary;
j1.salary = j2.salary;
j2.salary = t1;
t2 = j1.floor;
j2.floor = t2;
}
void show(job &j)
{
cout << j.name << ": $" << j.salary << " on floor " << j.floor << endl;
}
// template void Swap<int>(int, int); // 显式实例化,使用swap模板生成int类型的函数定义,前缀template
template <>
void Swap<int>(int &, int &); // 显式具体化,前缀template<>
// 编译器优先使用哪个函数?
/*从函数最优到最差的排列
1.完全匹配,但常规函数优先于模板
2.提升转换(char/shorts => int , float => double)
3.标准转换(int => char, long => double)
4.用户定义的转换,如类声明中定义的转换
*/
void may(int); // #1
float may(float, float = 3); // #2
void may(char); // #3
char *may(const char *); // #4
char may(const char &); // #5
template <class T>
void may(const T &); // #6
template <class T>
void may(T *); // #7
// 针对以下语句: may('A');
/*首先,4,7.char类型无法转换为char
#1 为提升转换
#2 为标准转换
#3 为常规函数完全匹配
#5 为常规函数完全匹配
#7 为模板函数完全匹配
*/
// 完全无关紧要的转换
/*
Type <=> Type&
Type[] => *Type
Type => const Type/ volatile Type
Type* => const Type/ volatile Type*
但在其中非const数据指针和引用优先与非const数据指针和引用匹配
*/
// 都是模板函数,更具体的模板函数优先(一般是显式具体化)
具体函数模板如何排序?
生成的过程中转换更少(c++ primer plus page 291)
以下是对于原书中tempover.cpp的理解&注释
// tempover.cpp --- template overloading
#include <iostream>
template <typename T> // template A
void ShowArray(T arr[], int n); // 传递数组的名字和个数
template <typename T> // template B
void ShowArray(T *arr[], int n);
struct debts
{
char name[50];
double amount;
};
int main()
{
using namespace std;
int things[6] = {13, 31, 103, 301, 310, 130};
struct debts mr_E[3] =
{
{"Ima Wolfe", 2400.0},
{"Ura Foxe", 1300.0},
{"Iby Stout", 1800.0}}; // 定义结构体数组
double *pd[3]; // 定义double指针类型数组
// set pointers to the amount members of the structures in mr_E
for (int i = 0; i < 3; i++)
pd[i] = &mr_E[i].amount; // 要取地址
cout << "Listing Mr. E's counts of things:\n";
// things is an array of int
ShowArray(things, 6); // uses template A
cout << "Listing Mr. E's debts:\n";
// pd is an array of pointers to double
ShowArray(pd, 3);
// 此处使用template B更匹配,如果删去template B就会用A输出struct的地址
return 0;
}
template <typename T>
void ShowArray(T arr[], int n)
{
using namespace std;
cout << "template A\n";
for (int i = 0; i < n; i++)
cout << arr[i] << ' ';
cout << endl;
}
template <typename T>
void ShowArray(T *arr[], int n) // 传入指针
{
using namespace std;
cout << "template B\n";
for (int i = 0; i < n; i++)
cout << *arr[i] << ' ';
cout << endl;
}
关键字decltype
template <class T1, class T2>
void ft(T1 x, T2 y)
{
/*
...
*/
decltype(x + y) xpy = x + y; // 使得xpy的数据类型和x+y相同
}
double x;
decltype(x) y; // y is a double
double &w;
decltype(w) y; // y is &
long fnn(int a);
decltype(fnn(2)) y; // y is long
double z;
decltype((z)) y; // y is &
short a;
char c;
decltype(a + c) y; // y is int(char + short 0 == int)
当函数返回类型无法确定时,先使用auto占位
template <class T1, class T2>
auto fnnnn(T1 a, T2 b) -> decltype(a + b) // 在声明a,b之后再用decltype写清楚返回类型
{
return a + b;
}
习题8(部分):
(如有错误请指正)
1.内联函数:直接代替调用函数的语句 => 代码量少,非递归
2.
a.
void song(const char* name, int times = 1);
b. 原型不需要修改
c. 右边必须也要赋默认值,否则需要交换顺序
void song(const char* name = "O,My Papa", int times = 1);
6.
// 6.a
double mass(double density, double volume = 1.0)
{
return density * volume;
} // 或者使用重载
// 6.b
void repeat(int a, const string h);
void repeat(const string h);
// 6.c
template <class T>
auto average(T a, T b) -> decltype(a + b);
// or
int average(int a, int b);
double average(double a, double b);
// 6.d:不行
8.
template <>
box max(box b1, box b2)
{
return b1.vol > b2.vol ? b1 : b2;
}
9. v1 => float , v2 => float &, v3 => float &, v4 => int, v5 => double