模板

模板

数据结构:能够存在任意类型

算法:能够操作任意类型

模板函数

类实例化 — 对象 模板实例化 ---- 函数代码

参数类型推导(作用在运行期)

decltype(a + b) 自动推导类型 表达式---- 类型

声明 = 定义和声明 都要写在头文件里

#include<iostream>
#include<algorithm>
using namespace std;

class A {
public:
    A() = delete;
    A(int x) : x(x) {}
    A operator+(const A &a) {
        return A(x +a.x);
    }
private:
    int x;
};

auto func(int a, int b)-> int {
    return 1;
}
//整一段都是声明(声明定义)  因为是作用在编译期前  必须写在头文件中

//用decltype  确认返回值类型
//每个类型都有构造函数, 但是有些类型没有默认构造所以有bug
/*
template<typename T1, typename T2>
decltype(T1() + U()) add(T1 a, T2 a) {
	return a + b;
}

*/
// 返回值后置可以解决多个参数返回值的bug
template<typename T1 ,typename T2>
auto add(T1 a, T2 b)->decltype(a + b) { 
    return (b + a);
}
int main() {
    int();    
    cout << add<int>(1, 1.1) << endl;//显示调用可以强行的转成int
    cout << add(1.1, 1.1) << endl;
    decltype(1 + 2) x; // 自动推导类型
    cout << typeid(x).name() << endl;
    return 0;
}


模板类 模板成员函数

使用的时候必须显示定义类型

#include<iostream>
#include<algorithm>
using namespace std;

template<typename T>
class PRINT {
public:
    //template<typename T>  这样就可以实现打印任意类型
    PRINT &operator()(T a) {
        cout << a << endl;
        return *this;
    }
};

int main() {
    PRINT<int> print;// 必须显示写上类型
    print(123);
    print(456);
   // print("aaa");
    PRINT<string> print1;
    
    return 0;
}

实现一个vector模板类

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

class A {
public:
    A() = delete;      //如果一个类没有默认构造就不能用new进行分配空间
    A(int x) : x(x) {}
private:
    int x;
};

namespace haizei {

template<typename T>
class vector {
public:
    vector(int n = 10):__capacity(n),__size(0), data(nullptr) {
        data = (T *)malloc(sizeof(T) * __capacity);  // 不能用new 如果没有默认构造就有bug
    }
    vector(const vector<T> &v) {
        __size = v.__size;
        __capacity = v.__capacity;
        data = (T *)malloc(sizeof(T) * __capacity);
        for (int i = 0; i < __size; i++) {
            //data[i] = v.data[i];  //malloc出来的空间并没有进行初始化如果这个类没有=运算符就出错了
            new(data + i) T(v.data[i]); //原地构造
        }
        return ;
        
    }
    vector(vector<T> &&v) : __capacity(v.__capacity),__size(v.__size), data(v.data){
        v.data = nullptr;
        v.__size = 0;
    }
    T &operator[](int ind) {
        return data[ind];
    }
    int size() const {
        return __size;
    }

    ~vector() {
        if (data) free(data);
        __size = 0;
        __capacity = 0;
        return ;
    }
private:
    int __size, __capacity;
    T *data;
};

};

int main() {
    vector<A> v1;
    haizei::vector<A> v2;
    cout << v1.size() << endl;
    cout << v2.size() << endl;

    return 0;
}

引用折叠

在模板中 &&是告诉编译器要传引用了 编译器会根据左值右值引用去推导 T的类型是 int & 还是 int &&

只有一个& 只能是左值引用。

奇数左值引用(T 的类型可能推导成为 int & – int &&&) 偶数右值引用(T的类型可能被推导为 int && – int &&&&)

typename remove_reference::type 可以把T类型的引用去掉

#include<iostream>
#include<algorithm>
using namespace std;

namespace haizei {
template<typename T>
void swap(T &a, T &b) {
    T c;
    c = a; a = b; b = c;
    return ;
}
/* 
void swap(T &&a, T &&b) {
    T c;   //这里会出错  在模板中 T&& 不是右值引用  而是告诉编译器要传引用了  所以T c  -- T &c  没有初始化报错了
    c = a; a = b; b = c;
    return ;
}

void swap(T &&a, T &&b) {
	typename remove_reference<T>::type c; // 可以把T类型的引用去掉
	c = a; a = b; b = c;
	return ;
}

*/    
};
int main() {
    int n = 123, m = 456;
    haizei::swap(n, m);
    haizei::swap(789, n); //这里出错了 右值绑定在左值引用上
}

模板偏特化 和 特化

类似模板的重载

特化模板的特性差不多没了 要写template<> 告诉编译器还是个模板(类似字面量)处理特殊场景

当显示调用的时候还是要去调用模板 (特化和直接写的区别)

#include<iostream>
#include<algorithm>
using namespace std;


template<typename T1 ,typename T2>
auto add(T1 a, T2 b)->decltype(a + b) { // 返回值后置
    return (b + a);
}

template<typename T1 ,typename T2>
auto add(T1 *a, T2 *b)->decltype(*a + *b) { // 模板偏特化 传指针用这个类似重置
    return (*b + *a);
}
//模板特化
template<>
int add(int a, int b) {
    return a + 2 * b;
}

int main() {
    decltype(1 + 2) x; // 自动推导类型
    int a = 1, b = 10;
    int *p  = &a, *q = &b;
    return 0;
}

变参模板

递归展开 …ARGS 里面的内容 要有一个递归终止 所以加上一个偏特化版的只穿一个参数的

#include<iostream>
#include<algorithm>
using namespace std;

template<typename T>
void print(T a) {
    cout << a << endl;
    return ;
}

template<typename T, typename ...ARGS>
void print(T a, ARGS... args) {
    cout << a << endl;
    print(args...);   //递归展开  要有一个出口
    return ;
}

int main() {
    print(123, "hello", "haizei", 45);
    return 0;
}

设计一个工具 如何拿到变参列表里面个个参数的类型 — 递归展开

#include<iostream>
#include<algorithm>
using namespace std;

template<typename T, typename ...ARGS>
struct N_ARGS {
    typedef T type;
    typedef N_ARGS<ARGS...> rest;
};

template<typename T>
struct N_ARGS<T> {
    typedef T type;
    typedef T last;
};

template<typename T>
void print(T a) {
    cout << a << endl;
    return ;
}

template<typename T, typename ...ARGS>
void print(T a, ARGS... args) {
    cout << a << "next type" << typeid(typename N_ARGS<ARGS...>::type).name() <<  endl;
    print(args...);

    return ;
}


int main() {
    print(123, "hello", "haizei", 45);
    N_ARGS<int, int ,double, double>::type x;
    N_ARGS<int, int ,double, double>::rest::type y;
    N_ARGS<int, int ,double, double>::rest::rest::type z;
    N_ARGS<int, int ,double, double>::rest::rest::rest::last k;
    return 0;
}

优化上面的功能

#include<iostream>
#include<algorithm>
using namespace std;

template<typename T, typename ...ARGS>
struct N_ARGS {
    typedef T type;
    typedef N_ARGS<ARGS...> rest;
};

template<typename T>
struct N_ARGS<T> {
    typedef T type;
    typedef T last;
};

template<typename T>
void print(T a) {
    cout << a << endl;
    return ;
}

template<typename T, typename ...ARGS>
void print(T a, ARGS... args) {
    cout << a << "next type" << typeid(typename N_ARGS<ARGS...>::type).name() <<  endl;
    print(args...);
    return ;
}

template<int N, typename T, typename ...ARGS>
struct NEW_N_ARGS {
    typedef typename NEW_N_ARGS<N - 1, ARGS...>::type type;
    static int last() {
        return NEW_N_ARGS<N - 1, ARGS...>::last();
    }
};

template<typename T, typename ...ARGS>
struct NEW_N_ARGS<1, T, ARGS...> {
    typedef T type;
    static int last() {
        return 0;
    }
};

template<typename T>
struct NEW_N_ARGS<1, T> {
    typedef T type;
    static int last() {return 1;}
};


int main() {
    print(123, "hello", "haizei", 45);
    //N_ARGS<int, int ,double, double>::type x;
    //N_ARGS<int, int ,double, double>::rest::type y;
    //N_ARGS<int, int ,double, double>::rest::rest::type z;
    //N_ARGS<int, int ,double, double>::rest::rest::rest::last k;

    NEW_N_ARGS<1, int, int ,double, double>::type x;
    NEW_N_ARGS<2, int, int ,double, double>::type y;
    NEW_N_ARGS<3, int, int ,double, double>::type z;
    NEW_N_ARGS<4, int, int ,double, double>::type k;
    

    return 0;
}

模板的图灵完备性

用模板去实现功能(累加 判断)

#include<iostream>
#include<algorithm>
using namespace std;


template<int N>
struct is_prime{
    static constexpr int r = 0;
};

template<int n>
struct sum {
    static constexpr int r = n + sum<n - 1>::r;
};

template<>
struct sum<1> {          //递归累加
    static constexpr int r = 1;
};

template<int n>
struct getBad {
    static constexpr int r = (n <= 5);
};

template<int n>
struct getGood {
    static constexpr int r = (n > 5);
};

template<int n, int m>   // if分支
struct judge;

template<>   
struct judge<1, 0> {
    static constexpr char * const r = (char *)"bad";
};

template<>
struct judge<0, 1> {
    static constexpr char * r = (char *)"good";
};
template<int n>
struct score {
    static constexpr char *r = judge<getBad<n>::r, getGood<n>::r>::r;   
};

template<int n>
struct is_even {
    static constexpr int r = (n % 2) ? 1 : 0;
};

int main() {
    cout << sum<5>::r << endl;
    cout << score<10>::r << endl;
    cout << score<4>::r << endl;
    cout << is_even<3>::r << endl;
    return 0;
}

检查素数

#include <iostream>
#include <cmath>
using namespace std;

template <int N, int M>
struct divd {
    static constexpr int a = !(N % M) ? 0 : divd<N, M - 1>::a; 
};
template <int N>
struct divd<N, 1> {
    static constexpr int a = 1;
};


template <int N>
struct is_prime {
    static constexpr char *r = divd<N, (int)sqrt(N)>::a == 0 ? (char *)" No" : (char *)" Yes";
};

int main() {
    constexpr int a = 2; 
    constexpr int b = 5; 
    constexpr int c = 35; 
    constexpr int d = 17; 
    constexpr int e = 97; 
    constexpr int f = 651; 
    constexpr int g = 23; 
    constexpr int h = 499; 
    
    cout << a << is_prime<a>::r << endl;
    cout << b << is_prime<b>::r << endl;
    cout << c << is_prime<c>::r << endl;
    cout << d << is_prime<d>::r << endl;
    cout << e << is_prime<e>::r << endl;
    cout << f << is_prime<f>::r << endl;
    cout << g << is_prime<g>::r << endl;
    cout << h << is_prime<h>::r << endl;

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值