原 C++ 函数模板 实例化和具体化

2024-05-04 04:18

本文主要是介绍原 C++ 函数模板 实例化和具体化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

https://blog.csdn.net/qq_30835655/article/details/76850894

函数模板是C++新增的一种性质,它允许只定义一次函数的实现,即可使用不同类型的参数来调用该函数。这样做可以减小代码的书写的复杂度,同时也便于修改。但是,在代码中包含函数模板本身并不会生成函数定义,它只是一个用于生成函数定义的方案。编译器使用模板为特定类型生成函数定义时,得到的是模板实例(instantiation)。

1 实例化

实例化有两种形式,分别为显式实例化和隐式实例化。模板并非函数定义,实例式函数定义。
1.1 显式实例化(explicit instantiation)

显式实例化意味着可以直接命令编译器创建特定的实例,有两种显式声明的方式。

比如存在这么一个模板函数

template <typename T>
void Swap(T &a, T &b)

第一种方式是声明所需的种类,用<>符号来指示类型,并在声明前加上关键词template,如下:
template void Swap<int>(int &, int &);

第二种方式是直接在程序中使用函数创建,如下:

Swap<int>(a,b);

显式实例化直接使用了具体的函数定义,而不是让程序去自动判断。
1.2 隐式实例化(implicit instantiation)

隐式实例化比较简单,就是最正常的调用,Swap(a,b),直接导致程序生成一个Swap()的实例,该实例使用的类型即参数a和b的类型,编译器根据参数来定义函数实例。


2 具象化(显式)
思考这么一个问题,当前的Swap模板交换输入的两个对象,可能式基本类型也可能式自定义类。如果有这么一个需求,需要交换自定义类里的某一个属性而不是整个类,那么Swap模板就不可用,因为Swap模板交换的是整个类。
显式具体化将不会使用Swap()模板来生成函数定义,而应使用专门为该特定类型显式定义的函数类型。有两种定义形式,如下,其中job为用户自定义类
template <> void Swap(job &a, job &b)
template <> void Swap<job>(job &a, job &b)
显式具体化在声明后,必须要有具体的实现,这是与显示实例化不同的地方。

3 举例
下面通过一个程序来观察实例化和具体化,加深理解。

    /*************************************************************************
        > File Name: array.cpp
        > Author:
        > Mail:
        > Created Time: Sat 05 Aug 2017 01:20:31 AM PDT
     ************************************************************************/
     
    #include<iostream>
    #include<string>
    using namespace std;
     
    struct job
    {
        string name;
        int salary;
        job(string _name,int _salary):name(_name),salary(_salary){};
    };
     
    //template prototype
    template <typename T>
    void Swap(T &a, T &b){
        T temp;
        temp = a;
        a = b;
        b = temp;
    }
     
    //explict specialization for job 显式具体化
    template <> void Swap(job &a, job &b)
    {
        int temp;
        temp = a.salary;
        a.salary = b.salary;
        b.salary = temp;
    }
     
    template void Swap<int>(int &, int &);
    int main()
    {
        char a = 'a', b = 'b';
        cout<<"a: "<<a<<" ; b: "<<b<<endl;
        Swap(a,b);  //1 implicit template instantiation for char 隐式实例化
        cout<<"a: "<<a<<" ; b: "<<b<<endl;
     
        int c = 1, d = 2;
        cout<<"c: "<<c<<" ; d: "<<d<<endl;
        Swap(c,d);  //2 use explicit template instantiation for int 显式实例化
        cout<<"c: "<<c<<" ; d: "<<d<<endl;
       
        Swap<int>(c,d);  //3 use explict template instantiation for int 显式实例化
        cout<<"c: "<<c<<" ; d: "<<d<<endl;
        
        job e("lucy",100), f("bob",200);
        cout<<"lucy: "<<e.name<<" "<<e.salary<<" ; bob: "<<f.name<<" "<<f.salary<<endl;
        Swap(e,f);  //use explict specialization for job 调用显式具体化
        cout<<"lucy: "<<e.name<<" "<<e.salary<<" ; bob: "<<f.name<<" "<<f.salary<<endl;
    }


输出

    ➜  cpptest ./a.out      
    a: a ; b: b
    a: b ; b: a
    c: 1 ; d: 2
    c: 2 ; d: 1
    c: 1 ; d: 2
    lucy: lucy 100 ; bob: bob 200
    lucy: lucy 200 ; bob: bob 100


备注:隐式实例化和显式实例化和显式具体化统称为具体化,它们的相同在于都用了具体类型的函数定义,而不是通用描述。
---------------------  
作者:尹小贱  
来源:CSDN  
原文:https://blog.csdn.net/qq_30835655/article/details/76850894  
版权声明:本文为博主原创文章,转载请附上博文链接!

 

这篇关于原 C++ 函数模板 实例化和具体化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/958322

相关文章

C++ move 的作用详解及陷阱最佳实践

《C++move的作用详解及陷阱最佳实践》文章详细介绍了C++中的`std::move`函数的作用,包括为什么需要它、它的本质、典型使用场景、以及一些常见陷阱和最佳实践,感兴趣的朋友跟随小编一起看... 目录C++ move 的作用详解一、一句话总结二、为什么需要 move?C++98/03 的痛点⚡C++

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

C++构造函数中explicit详解

《C++构造函数中explicit详解》explicit关键字用于修饰单参数构造函数或可以看作单参数的构造函数,阻止编译器进行隐式类型转换或拷贝初始化,本文就来介绍explicit的使用,感兴趣的可以... 目录1. 什么是explicit2. 隐式转换的问题3.explicit的使用示例基本用法多参数构造

Java利用Spire.Doc for Java实现在模板的基础上创建Word文档

《Java利用Spire.DocforJava实现在模板的基础上创建Word文档》在日常开发中,我们经常需要根据特定数据动态生成Word文档,本文将深入探讨如何利用强大的Java库Spire.Do... 目录1. Spire.Doc for Java 库介绍与安装特点与优势Maven 依赖配置2. 通过替换

C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解

《C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解》:本文主要介绍C++,C#,Rust,Go,Java,Python,JavaScript性能对比全面... 目录编程语言性能对比、核心优势与最佳使用场景性能对比表格C++C#RustGoJavapythonjav

C++打印 vector的几种方法小结

《C++打印vector的几种方法小结》本文介绍了C++中遍历vector的几种方法,包括使用迭代器、auto关键字、typedef、计数器以及C++11引入的范围基础循环,具有一定的参考价值,感兴... 目录1. 使用迭代器2. 使用 auto (C++11) / typedef / type alias

C++ scoped_ptr 和 unique_ptr对比分析

《C++scoped_ptr和unique_ptr对比分析》本文介绍了C++中的`scoped_ptr`和`unique_ptr`,详细比较了它们的特性、使用场景以及现代C++推荐的使用`uni... 目录1. scoped_ptr基本特性主要特点2. unique_ptr基本用法3. 主要区别对比4. u

C++11中的包装器实战案例

《C++11中的包装器实战案例》本文给大家介绍C++11中的包装器实战案例,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录引言1.std::function1.1.什么是std::function1.2.核心用法1.2.1.包装普通函数1.2.

C++多线程开发环境配置方法

《C++多线程开发环境配置方法》文章详细介绍了如何在Windows上安装MinGW-w64和VSCode,并配置环境变量和编译任务,使用VSCode创建一个C++多线程测试项目,并通过配置tasks.... 目录下载安装 MinGW-w64下载安装VS code创建测试项目配置编译任务创建 tasks.js