跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • Online Tools
  • 用户
  • 群组
折叠
品牌标识

D2Learn Forums

  1. 主页
  2. Blogs | 博客
  3. Sunrisepeak's Blog
  4. 现代C++泛型编程初识 - 类模板到模板特例化及具体应用示例

现代C++泛型编程初识 - 类模板到模板特例化及具体应用示例

已定时 已固定 已锁定 已移动 Sunrisepeak's Blog
现代c++mcpp泛型编程元编程模板
1 帖子 1 发布者 26 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • SPeakS 离线
    SPeakS 离线
    SPeak d2learn-dev
    编写于 最后由 SPeak 编辑
    #1

    文章导读

    • 一、类模板与模板特化(全特化与偏特化)
    • 二、类模板与其模板特化的应用
    • 三、模板特化存在性问题

    一、类模板与模板特化(全特化与偏特化)

    从接受类型的角度
    类模板:全集R
    模板偏特化(部分特化):为全集的一个子集A
    模板全特化:为R中的一个"点",或者说为R中的一个元素
    匹配规则:越特化匹配优先级越高(见下面例子)

    98a9da6a-01af-4fc4-83ad-91b7ca549699-image.png

    1.类模板

    可以接受任意类型

    // R
    template<typename T>
    class A {};    // 类模板是能接受任意类型,A后面不需要(不能)任何处理
    

    2.模板偏特化(局部特化)

    可以接受任意指针类型

    // A
    template<typename T>
    class A<T *> {};    // 类模板A的偏特化版本,在A后指出特化的范围
    

    3.模板全特化

    指定接受int类型

    template<>
    class A<int> {}    // 类模板A的全特化版本(已经是类模板的一个实例了),在A后直接指出明确类型int
    

    4.例子:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    template<typename T>
    class A {
    public:
        A() {
    	cout << "R" << endl;
        }
    };
    
    /* 注释1 -- 接受指针
    template<typename T>
    class A<T *> {
    public:
        A() {
    	cout << "A" << endl;
        }
    };
    */
    
    /* 注释2 -- 接受int
    template<>
    class A<int> {
    public:
        A() {
    	cout << "int" << endl;
        }
    };
    */
    
    int main() {
        A<string> r;    // 1
        A<char *> a;    // 2
        A<int> i;       // 3
        return 0;
    }
    

    5.测试不同情况:

    当只有一个类模板(可接受任意类型R)存在时,1, 2, 3都使用类模板实例化

    v2-a53836d6d2a913d69c2fd90b0dd4371f_1440w.png

    注释1是接受所以指针类型(R的子集A),所以称其为类模板A的偏特化(范围特化)。即把类模版A所能接受的指针类型单独处理(实例化)。当取消注释1时:char * 将由这个模板类A的偏特化版本(范围特化,局部特化)处理。

    v2-2bd02b7f6a4dbb5cdbc586f98d76b92b_1440w.png

    注释2只接受int类型的参数(可以看出是全局R中的一个元素)。当你用int实例化A时,将会由这个全特化版本来实现(而不会使用可以接受任意类型的版本(泛化版))。

    v2-6a08120bfe6da8471d8fb374b2665a65_1440w.png

    二、类模板与其模板特化的应用

    用模板的偏特化 实现一个 能移除任意类型const属性的模板类:remove_const
    主要功能和用法:
    功能:
    给remove_const一个类型后
    --1.(情况1)如果这个类型没有const属性则获得这个类型本身。
    --2.(情况2)如果这个类型有const属性则移除它。
    用法:
    remove_const<Type>::type
    使用场景:
    当拿到一个未知变量时,想获得这个变量(或对象)的非const的类型
    

    1.实现情况1

    似乎没做什么事,aa是int符合情况1。但情况2不符合,bb没有变成int。

    #include <iostream>
    #include <type_traits>
    
    template<typename T>
    struct remove_const {
        using type = T;
    };
    
    
    int main() {
        int a = 1;
        const int b = 2;
        remove_const<decltype(a)>::type aa = 3;
        remove_const<decltype(b)>::type bb = 4;
        std::cout << std::is_same<decltype(aa), int>::value << std::endl;
        std::cout << std::is_same<decltype(bb), int>::value << std::endl;
        return 0;
    }
    

    运行结果:
    v2-7a36de2df8473699ecc173f27351c876_1440w.png

    2.实现情况2

    从上面的实现可以看出,当传给模板的参数是带const类型时它还会返回带const属性的类型。同时从remove_const的定义也可以看出他是个 复读机 你给他什么类型他就给你什么类型。

    这时候可以使用上面介绍的偏特化的性质,来把带有带const的类型这个子集从全集中分离出来 特殊处理。如下:

    #include <iostream>
    #include <type_traits>
    
    template<typename T>
    struct remove_const {
        using type = T;
    };
    
    template<typename T>
    struct remove_const<const T> {
        using type = T;
    };
    
    int main() {
        int a = 1;
        const int b = 2;
        remove_const<decltype(a)>::type aa = 3;
        remove_const<decltype(b)>::type bb = 4;
        std::cout << std::is_same<decltype(aa), int>::value << std::endl;
        std::cout << std::is_same<decltype(bb), int>::value << std::endl;
        return 0;
    }
    

    运行结果:

    给带const的类型,写了一个特化版本。所以当remove_const接受一个带const的类型时,就会通过这个偏特化版本实例化,由于这个偏特化版本把const从类型中分离出来了,则这里的T就是没有const的类型,从而实现去除类型const的功能。

    v2-d337e4dc338fc9a90fcfa7ef9db27804_1440w.png

    三、模板特化存在性问题

    一个类模板的特化,是对某一个类模板的子集做特化处理的。而它不能"独立存在"。既只有存在一个类模板X, 才能存在对它特化的版本。

    template<typename T>
    class A<T *> {};
    
    int main() { return 0; }
    

    v2-1023f2d6ec20e5efa6300629068527d6_1440w.png

    1 条回复 最后回复
    1

    • 登录

    • 没有帐号? 注册

    • 登录或注册以进行搜索。
    d2learn forums Powered by NodeBB
    • 第一个帖子
      最后一个帖子
    0
    • 版块
    • 最新
    • 标签
    • 热门
    • Online Tools
    • 用户
    • 群组