【C++】你想要的——印刷模板儿(上)

简介: 【C++】你想要的——印刷模板儿

一、泛型编程

泛型编程是什么意思呢?我们通过下面的例子来具体了解:

void Swap(int& left, int& right)
{
  int temp = left;
  left = right;
  right = temp;
}
void Swap(double& left, double& right)
{
  double temp = left;
  left = right;
  right = temp;
}
int main()
{
  int a = 1, b = 2;
  Swap(a, b); 
    double c=1.33,d=2.33;
    Swap(a,b)
}

就拿交换函数来说,当我们交换不同类型的变量的值,那就需要不停的写交换函数的重载,这样代码复用率就较低,那我们能不能创造一个模板呢??


一个Swap的模板,但是我可以用不同的类型去实现这个模板,继而试用它。


如果在 C++ 中,也能够存在这样一个 模具 ,通过给这个模具中 填充不同材料 ( 类型 ) ,来 获得不同材料的铸件 ( 即生成具体类型的代码)。

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。

二、模板(初阶)

模板分为:函数模板和类模板


1.函数模板

1.单参数类型

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定 类型版本。

就拿Swap来说:  typename 是 用来定义模板参数 关键字,T是类型(也可以用class,(class T))

template<typename T>
void Swap(T& left, T& right)
{
  T temp = left;
  left = right;
  right = temp;
}
int main()
{
      int a = 1, b = 2;
      Swap(a, b);
        int x = 1, y = 2;
    Swap(x, y);
    double m = 1.1, n = 2.2;
    Swap(m, n);
    char p = 'a', q = 'b';
    Swap(p, q);
        Swap(m,a);//不同类型
}

那么,具体是怎样实现的呢?

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。

编译器通过类型推演,将函数模板进行实例化,对应的T就会替换成具体的类型,模板实例化是用几个实例化几个,不是所有不同类型都提前模板实例化。


1.当变量类型相同,但是变量不同,调用Swap();模板实例化只会实例化一个,因为虽然变量不同,但类型相同,模板实例化就是将T换成具体的类型。


2.当Swap(m,a),变量是不同类型时,会发生什么??


因为在推演void Swap(T& left, T& right);时,T的类型不明确,就会发生错误(推演报错),直接报错


但如果不用模板,我们自己这样:

void Swap(int& left, int& right)
{
  int temp = left;
  left = right;
  right = temp;
}
int main()
{
  int a=2;
  double b=2.22;
  Swap(a,b);
}

可能有人就会想:在Swap(a,b)中,会不会a和b发生饮食类型转化呢?较小的类型转化成较大的类型。


当然不会:隐式类型转化只有在 赋值:b=3;(产生临时变量);函数传参的时候(产生临时变量),才会发生隐式类型转化。


函数形参是引用,当类型是引用时,我们就要小心:是否会发生权限放大?当b传值时,中间的临时变量具有常性(只读),而形参是可读可写,权限就会放大,也是不可以通过的,除非加了const,但是加了const就无法交换了,所以这样还是行不通的!


自动推演实例化和显式实例化:

template<class T>
T Add(const T& left, const T& right)
{
  return left + right;
}
int main()
{
  int a1 = 10, a2 = 20;
  double d1 = 10.1, d2 = 20.2;
  // 自动推演实例化
  cout << Add(a1, a2) << endl;
  cout << Add(d1, d2) << endl;
  cout << Add((double)a1, d2) << endl; //强制类型转化也是产生临时变量,不是改变a1
  cout << Add(a1, (int)d2) << endl;
  // 显示实例化
  cout << Add<double>(a1, d2) << endl;//隐式类型转化
  cout << Add<int>(a1, d2) << endl;
  return 0;
}

在自动推演实例化中,必须强转,不然还是和之前问题一样,该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,编译器无法确定此处到底该将T确定为int 或者 double类型而报错。 (推演报错)


不强转情况:显示实例化,:在函数名后的<>中指定模板参数的实际类型(我让你怎么来你就怎么来!)


在函数名后加入了指定模板参数后,就会在实例化时,T直接是指定的类型,这样就会发生隐式类型转换。


注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅

Add(a1, d1);

此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化

2.多参数类型

template

template<class t1,class t2>
t1 Add(const t1& left, const t2& right)
{
  return left + right;
}
int main()
{
  int a = 1, b = 2;
  double m = 2.22, n = 3.33;
  cout << Add(a, b) << endl;
  cout << Add(m, n) << endl;
  cout << Add(a, m) << endl;
  cout << Add(n, b) << endl;
}

此时,当Add(不同类型时),就不会发生推演错误,你是什么类型就会推演成什么模板函数


目录
相关文章
|
7天前
|
安全 编译器 C++
C++一分钟之-编译时计算:constexpr与模板元编程
【6月更文挑战第28天】在C++中,`constexpr`和模板元编程用于编译时计算,提升性能和类型安全。`constexpr`指示编译器在编译时计算函数或对象,而模板元编程通过模板生成类型依赖代码。常见问题包括误解constexpr函数限制和模板递归深度。解决策略包括理解规则、编写清晰代码、测试验证和适度使用。通过实战示例展示了如何使用`constexpr`计算阶乘和模板元编程计算平方。
30 13
|
4天前
|
存储 编译器 C++
【C++】详解C++的模板
【C++】详解C++的模板
|
3天前
|
C++ 开发者
C++一分钟之-编译时计算:constexpr与模板元编程
【7月更文挑战第2天】C++的`constexpr`和模板元编程(TMP)实现了编译时计算,增强代码效率。`constexpr`用于声明编译时常量表达式,适用于数组大小等。模板元编程则利用模板进行复杂计算。常见问题包括编译时间过长、可读性差。避免方法包括限制TMP使用,保持代码清晰。结合两者可以解决复杂问题,但需明确各自适用场景。正确使用能提升代码性能,但需平衡复杂性和编译成本。
13 3
|
2天前
|
编译器 C语言 C++
【C++】模板初阶(下)
C++的函数模板实例化分为隐式和显式。隐式实例化由编译器根据实参推断类型,如`Add(a1, a2)`,但`Add(a1, d1)`因类型不一致而失败。显式实例化如`Add&lt;double&gt;(a1, d1)`则直接指定类型。模板函数不支持自动类型转换,优先调用非模板函数。类模板类似,用于创建处理多种数据类型的类,如`Vector&lt;T&gt;`。实例化类模板如`Vector&lt;int&gt;`和`Vector&lt;double&gt;`创建具体类型对象。模板使用时,函数模板定义可分头文件和实现文件,但类模板通常全部放头文件以避免链接错误。
|
2天前
|
机器学习/深度学习 算法 编译器
【C++】模板初阶(上)
**C++模板简介** 探索C++泛型编程,通过模板提升代码复用。模板作为泛型编程基础,允许编写类型无关的通用代码。以`Swap`函数为例,传统方式需为每种类型编写单独函数,如`Swap(int&)`、`Swap(double&)`等,造成代码冗余。函数模板解决此问题,如`template&lt;typename T&gt; void Swap(T&, T&)`,编译器根据实参类型推导生成特定函数,减少重复代码,增强可维护性。模板分函数模板和类模板,提供处理不同数据类型但逻辑相似的功能。
|
2天前
|
算法 编译器 程序员
|
2天前
|
存储 编译器 程序员
|
5天前
|
安全 C++
详细解读c++异常模板复习
详细解读c++异常模板复习
|
8天前
|
存储 算法 编译器
程序与技术分享:C++模板元编程简介
程序与技术分享:C++模板元编程简介
|
8天前
|
SQL 人工智能 算法
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer