zoukankan      html  css  js  c++  java
  • c++模板笔记

    使用vc2015
    进行C++ 模板的学习实验和笔记 用简单示例学习了解STL


    template大部头理论书 讲解各种规则和各种规则例外的解决办法 集中精力在20%的规则中的阴暗角落而不是80%实践中要注意的东西

    https://github.com/wuye9036/CppTemplateTutorial
    这个模板教程是强烈推荐 易懂 看完可用于个人的一些代码中进行模板编程 实用


    第一个示例
    //=============================================
    int add(int a ,int b)
    {
    return a+b;
    }

    int main()
    {
    add(3,8);
    add(7,12);
    return 0;
    }
    //============================================
    如果说
    函数是变量之间的操作方式复用方案
    比如 3+8 7+12 都是调用add函数
    那么模板就是变量的类型的复用方案
    比如

    #include <iostream>
    template<typename T>
    const T& compare(T& a, T& b)
    {
    return a > b? a :b;
    }

    int main()
    {
    int a = 7, b = 8, c = 9, d = 3;
    std::cout << compare<int>(a, b) << std::endl;
    std::cout << compare(c, d) << std::endl;
    char f = 'f', g = 'z';
    std::cout << compare(f, g) << std::endl;
    return 0;
    }

    compare这个模板函数对于变量的比较方式都是一致的 ,就是比较两个变量的大小
    而且对于 int 和 char 两种变量类型的比较都适用
    就是我所说的对于变量的类型的复用方案
    由于模板T对应的变量类型在本例中可以从函数参数推导得出 所以<int>这个符号并不强制需要写出来。

    下面示例是一个链表 链表中每个节点可以存储不同类型元素
    #include <iostream>
    #include <string>

    template<typename TYPE,typename NEXT>
    struct AnyList {
    TYPE value;
    NEXT* next;
    AnyList(TYPE const &v,NEXT *n):value(v),next(n){}
    };

    int main()
    {
    typedef AnyList<int, void> node_0;
    node_0 zero(4,NULL) ;
    typedef AnyList<char, node_0> node_1;
    node_1 one('z',&zero);
    typedef AnyList<std::string, node_1> node_2;
    node_2 two("test", &one);

    std::cout << two.value << std::endl;
    std::cout << one.value << std::endl;
    std::cout << zero.value << std::endl;

    std::cout << two.value << std::endl;
    std::cout << two.next->value << std::endl;
    std::cout << two.next->next->value << std::endl;

    return 0;
    }

    示意图:略

    STL中FOREACH示例学习(函数指针模板参数)
    #include <iostream>
    #include <string>

    template<typename T,void(*f)(T &v)>
    void foreach(T array[], unsigned size)
    {
    for (unsigned i = 0; i < size; ++i)
    f(array[i]);
    }

    template<typename T>
    void inc(T& v) { ++v; }

    template<typename T>
    void dec(T& v) { --v; }

    template<typename T>
    void print(T& v) { std::cout << ' ' << v << std::endl; }

    int main()
    {
    int array[] = { 1,2,3,4,5,6,7,8 };

    foreach<int, print<int>>(array, 8);
    std::cout << std::endl;

    foreach<int, inc<int>>(array, 8);
    foreach<int, print<int>>(array, 8);
    std::cout << std::endl;

    foreach<int, dec<int>>(array, 8);
    foreach<int, print<int>>(array, 8);
    std::cout << std::endl;

    return 0;
    }
    FOREACH函数从模板接收操作类型和操作函数,从参数中接收要操作的数组和数组长度
    //===============================================
    指针与引用模板参数

    #include <iostream>
    #include <string>

    template<typename T>
    class wrapper;

    template<typename T>
    class wrapper<T*> {
    public:
    T* p;
    wrapper(T* t):p(t){}
    T get() { return *p; }
    void set(T v) { *p = v; }
    };


    template<typename T>
    class wrapper<T&> {
    public:
    T& p;
    wrapper(T& t) :p(t) {}
    T get() { return p; }
    void set(T v) { p = v; }
    };


    int global_variable_int = 0;

    char global_variable_char = 'Z';

    std::string global_variable_str = "this is a test";

    int main()
    {

    wrapper<int*> gwrapper1(&global_variable_int);
    gwrapper1.set(1);
    std::cout << gwrapper1.get() << std::endl;

    wrapper<int&> gwrapper2(global_variable_int);
    gwrapper2.set(2);
    std::cout << gwrapper2.get() << std::endl;

    wrapper<char*> gwrapper3(&global_variable_char);
    gwrapper3.set('a');
    std::cout << gwrapper3.get() << std::endl;

    wrapper<char&> gwrapper4(global_variable_char);
    gwrapper4.set('g');
    std::cout << gwrapper4.get() << std::endl;

    wrapper<std::string*> gwrapper5(&global_variable_str);
    std::cout << gwrapper5.get() << std::endl;

    wrapper<std::string&> gwrapper6(global_variable_str);
    gwrapper6.set("finish test");
    std::cout << gwrapper6.get() << std::endl;

    return 0;
    }

    根据参数的不同 自动选择不同的模板函数 指针或者引用
    //======================================
    模板的模板参数
    如果模板中的模板不参与推导 可以省略不写
    #include <iostream>
    #include <string>

    //template<template<typename TT> class Func, typename T>
    template<template<typename> class Func, typename T>
    void foreach(T array[], unsigned size)
    {

    Func<T> func;
    for (unsigned i = 0; i < size; ++i)
    func(array[i]);
    }

    template<typename T>
    struct inc {
    void operator()(T& v) { ++v; }
    };

    int main()
    {
    int arr[] = { 1,2,3,4,5 };
    foreach<inc>(arr,5);
    return 0;
    }

    //====================================================
    特化匹配示例
    // 11111.cpp : 定义控制台应用程序的入口点。
    //

    #include "stdafx.h"
    #include <iostream>
    #include <string>

    template<typename T0,typename T1,typename T2>
    struct S {
    std::string id() { return "General"; }
    };

    template<typename T0,typename T1>
    struct S<T0, T1, char>
    {
    std::string id(){ return "#1"; }
    };

    template<typename T0>
    struct S<T0, char, char>
    {
    std::string id() { return "#2"; }
    };

    template<typename T>
    struct S<int, T, T>
    {
    std::string id() { return "#3"; }
    };


    int main()
    {
    std::cout << S<float, float, float>().id() << std::endl;
    std::cout << S<int, int, int>().id() << std::endl;
    std::cout << S<int, int, char>().id() << std::endl;
    std::cout << S<char, char, char>().id() << std::endl;
    // 歧义
    //std::cout << S<int, char, char>().id() << std::endl;

    return 0;
    }

    //========================================================
    模板的递归示例

    // 11111.cpp : 定义控制台应用程序的入口点。
    //

    #include "stdafx.h"
    #include <iostream>
    #include <string>

    template<int i>
    int mult()
    {
    return i * mult<i - 1>();
    }

    template<>
    int mult<1>()
    {
    return 1;
    }

    int main()
    {
    std::cout << "mult<4> = " << mult<4>();
    return 0;
    }

  • 相关阅读:
    Hibernate实现CRUD的例子小结
    AspnetPager表格标题排序功能
    Microsoft企业库配置问题
    orm比较
    外语培训网求鉴定
    DIV随滚动条滚动而滚动
    图片切换效果展示
    转载C#委托之多播委托( 二)
    LINQ 图解
    不用ajax调用搞后台小技巧
  • 原文地址:https://www.cnblogs.com/itdef/p/5746058.html
Copyright © 2011-2022 走看看