首页 > 代码库 > 【足迹C++primer】58、Template Parameter

【足迹C++primer】58、Template Parameter

Template Parameter
#include<iostream>
#include<algorithm>
#include<memory>
#include<list>
#include<fstream>
#include<string>

using namespace std;

template<typename Foo>
Foo calc(const Foo &a, const Foo &b)
{
    Foo temp=a;
    //...
    return temp;
}

///Template Parameters and Scope 模板参数和作用域
typedef double A;
template<typename A, typename B>
void f(A a, B b)
{
    A tmp=a;
//    double B; error:模板类型B,B是一个类型不是一个参数
}

///template Declarations 模板声明
template<typename T> int compare(const T &, const T &);
template<typename T> class Blob;

///使用类成员类型
template<typename T>    //T可以是一个类类型
typename T::value_type   //可以类似这个样得到类的值,这是一个返回类型
top(const T &c)
{
    if(!c.empty())
        return c.back();
    else
        return typename T::value_type();
}

/*
如果我们想要那个模板里的名字是一个类型,不是!!注意用的是“不是”,不是类class的
话,那么必须用typename来修饰,而不是class
*/

///Default Template Arguments 默认模板参数
template<typename T, typename F=less<T>>   //F默认为一个函数
int compare(const T &v1, const T &v2, F f=F())  //就是less<T>()
{
    if(f(v1, v2)) return -1;
    if(f(v2, v1)) return 1;
    return 0;
}

///模板默认参数和类模板
template<class T=int>   //这个int 就是T的默认类型
class Numbers
{
public:
    Numbers(T v=0):val(v) {}
private:
    T val;
};

void fun1()
{
    Numbers<long double> lots_of_precisions;
    Numbers<> average_precisions;
}

/**************************************
模板成员
**************************************/
class DebugDelete
{
public:
    DebugDelete(ostream &s=cerr):os(s) {}
    //不论任何函数模板,T的类型由编译器自行推导
    template<typename T>
    void operator()(T* p) const {os<<"deleting unique_ptr "<<endl; delete p;}
private:
    ostream& os;
};


void fun2()
{
    double* p=new double;
    DebugDelete d;  //d默认对象
    d(p);   //--->delete p;
    int* ip=new int;
    DebugDelete() (ip);
    unique_ptr<string, DebugDelete> sp(new string, DebugDelete());
}

/*
void DebugDelete::operator()(int* p) const {delete p;}
void DebugDelete::operator()(string* p) const {delete p;}
这两个就是上面那个过程的不用模板,类里面就要这样写
*/

///模板类里面的成员模板
template<typename> class BlobPtr;
template<typename> class Blob;

template<typename T>
bool operator==(const Blob<T> &, const Blob<T> &);

template<typename T>
class Blob
{
    friend class BlobPtr<T>;
    friend bool operator==<T> (const Blob<T> &, const Blob<T> &);

public:
    typedef T value_type;
    //using value_type=T;
    typedef typename vector<T>::size_type size_type;
//    using size_type=typename vector<T>::size_type;
    //构造函数
    template<typename It> Blob(It b, It e);
    Blob();
    Blob(initializer_list<T> il);   //参数连串初始化
    //元素个数
    size_type size() const {return data->size();}   //得到vector元素个数
    bool empty() const {return data->empty();}  //判断vector是否为空

    //加减元素,拷贝
    void push_back(const T &t) {data->push_back(t);}
    //移动版本,move,&&是右值引用!!
    void push_back(T &&t) { data->push_back(std::move(t));}

    void pop_back();    //删除一个元素
    //元素调用
    T &back();  //返回最后一个元素
    T &operator[](size_type i); //下标运算符
private:
    shared_ptr<vector<T>> data;
    void check(size_type i, const string &msg) const;
};

template<typename T>
template<typename It>
Blob<T>::Blob(It b, It e):data(make_shared<vector<T>>(b, e)){}

///成员模板实例化
void fun3()
{
    int ia[]={0,1,2,3,4,5,6,7,8,9};
    vector<long> vi={0,1,2,3,4,5,6,7,8,9};
    list<const char*> w={"now","is","the","time"};
    Blob<int> a1(begin(ia), end(ia));
    Blob<int> a2(vi.begin(), vi.end());
    Blob<string> a3(w.begin(), w.end());
}

/**************************************
16.2模板参数推演
**************************************/
///转化和模板类型参数
template<typename T> T fobj(T a, T b){cout<<"template<typename T> T fobj(T, T)"<<endl; return a;}
template<typename T> T fref(const T &a, const T &b){cout<<"template<typename T> T fref(const T &, const T &)"<<endl; return b;}

void fun4()
{
    string s1("a value");
    const string s2("another value");
    cout<<"fobj(s1, s2) s1:"<<fobj(s1, s2)<<endl;       //注意返回类型!!!
    cout<<"fref(s1, s2) s2:"<<fref(s1, s2)<<endl;


    int a[10], b[42];
    cout<<"fobj(a, b); a:"<<fobj(a,b)<<endl;

//    fref(a, b);  error:这是&引用,而a,b是int *一个指针
}

///函数的参数使用相同的模板形参类型
template<typename A, typename B>
int flexibleCompare(const A &v1, const B &v2)
{
    if(v1<v2) return -1;
    if(v2<v1) return 1;
    return 0;
}

void fun5()
{
    long lng=1111.0;
    cout<<"flexibleCompare(lng, 1024):"<<flexibleCompare(lng, 1024)<<endl;
}

template<typename T>
ostream &print(ostream &os, const T &obj) {return os<<obj<<endl;}

void fun6()
{
    print(cout, 42);
    ofstream f1("output.txt");
    print(f1, 10);
}

/**************************************
函数模板的显示实参
**************************************/
///指定一个显示形参
template<typename T1, typename T2, typename T3>
T1 sum(T2, T3){}
void fun7()
{
    int i;
    long lng;
    auto val3=sum<long long>(i, lng);
}
/*
只有确定返回类型后才可自行推导,如果只是知道后面几个类型那就没法推导了
说的是<long long >里面的类型,是第一个
*/

/**
尾返回类型和类型转换
*/
template<typename It>
auto fcn(It beg, It end) -> decltype(*beg)
{
    return *beg;
}

int main()
{
    cout<<">>------------------------------fun1-----------------------------------<<"<<endl;
    fun1();
    cout<<">>------------------------------fun2-----------------------------------<<"<<endl;
    fun2();
    cout<<">>------------------------------fun3-----------------------------------<<"<<endl;
    fun3();
    cout<<">>------------------------------fun4-----------------------------------<<"<<endl;
    fun4();
    cout<<">>------------------------------fun5-----------------------------------<<"<<endl;
    fun5();
    cout<<">>------------------------------fun6-----------------------------------<<"<<endl;
    fun6();
    cout<<">>------------------------------fun7-----------------------------------<<"<<endl;
    fun7();


    system("pause");
    return 0;
}