CPP学习笔记(自用)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值