泛化编程 day01

一、模板的起源

1、C/C++是静态的语言(编译型语言)

  • 1)这类语言有很多的数据类型(int/double/float等等…)在效率和安全性的方面是无可比拟的
  • 2)这类语言在很大程度上也给程序员编写通用代码带来瓶颈,使程序员不得不为每一种数据类型编写完全相同或几乎完全相同的代码实现,虽然他们在抽象层面是一致的

eg:type01.cpp

#include <iostream>
using namespace std;

int max_int(int x, int y)
{
    return x > y ? x : y;
}

double max_double(double x, double y)
{
    return x > y ? x : y;
}

string max_string(string x, string y)
{
    return x > y ? x : y;
}
int main(void)
{
    int nx=10, ny=20;
    cout << max_int(nx, ny) << endl;
    double dx=12.3, dy=45.6;
    cout << max_double(dx, dy) << endl;
    string sx="hello", sy="world";
    cout << max_string(sx, sy) << endl << endl;
    return 0;
}

2、借助参数宏可以摆脱数据类型的限制

  • 1)宏只是在预处理阶段针对代码的纯文本替换
  • 2)宏本身没有函数的语义(不会对数据类型进行检查
  • 3)因此借助参数宏虽然可以拜托类型的约束和限制,但同时也丧失了对数据类型的检查

eg:untype02.cpp

#include <iostream>
using namespace std;
#define Max(x, y) (x > y ? x : y)

int main(void)
{
    int nx=10, ny=20;
    cout << Max(nx, ny) << endl;
    //cout << (nx>ny?nx:ny) << endl;//純文本類型替換
    double dx=12.3, dy=45.6;
    cout << Max(dx, dy) << endl;
    string sx="hello", sy="world";
    cout << Max(sx, sy) << endl;//world
    char cx[256]="world", cy[256]="hello";
    cout << Max(cx, cy) << endl;//hello
    //cout << (cx>cy?cx:cy) << endl;//比較的是地址誰大
    return 0;
}

3、借助宏构建通用函数的框架

  • 1)通过实例化宏,让预处理将这个宏扩展针对不同数据类型的真正函数
  • 2)将宏的通用性函数的类型安全性完美结合起来

eg:marco03.cpp

#include <iostream>
using namespace std;
//##是拼接
#define MAX(T) T max_##T(T x, T y){\
    return x > y ? x : y;\
}

MAX(int)
//int max_int(int x, int y){return x>y ? x:y;}
MAX(double)
//int max_dooublc(double x, double y){...}
MAX(string)
//string max_string(string x, string y){...}

int main(void)
{
    int nx=10, ny=20;
    cout << max_int(nx, ny) << endl;
    double dx=12.3, dy=45.6;
    cout << max_double(dx, dy) << endl;
    string sx="world", sy="hello";
    cout << max_string(sx, sy) << endl;

    return 0;
}

eg:macro03_02.cpp

#include <iostream>
using namespace std;
//##是拼接
#define MAX(T) T max_##T(T x, T y){\
    return x > y ? x : y;\
}

MAX(int)
//int max_int(int x, int y){return x>y ? x:y;}
MAX(double)
//int max_dooublc(double x, double y){...}
MAX(string)
//string max_string(string x, string y){...}

#define Max(T) max_##T

int main(void)
{
    int nx=10, ny=20;
    cout << MAX(int)(nx, ny) << endl;
    double dx=12.3, dy=45.6;
    cout << MAX(double)(dx, dy) << endl;
    string sx="world", sy="hello";
    cout << MAX(string)(sx, sy) << endl;

    return 0;
}

二、函数模板

1、函数模板声明

  • 1)函数模板的声明形式:
template<class 类型形参1, class 类型形参2, ...>
返回值类型 函数模板名(调用形参1, 调用形参2, ...){
	...
}

eg:

template<class T>T Max(T x, T y){
	return x>y?x:y;
}

可以使用任何标识符作为类型形参的名称,但使用"T"已经成为一种惯例,"T"表示的是调用者在使用这个函数模板时指定的任意数据类型

2、函数模板的使用

  • 使用函数模板必须对模板进行实例化
  • 形式:函数模板名<类型实参1, 类型实参2,...>(调用实参1,...);

eg:

Max<int>(123, 456);
Max<double>(12.3,45.6);
Max<string>("hello", "world");

3、分析函数模板

  • 切记编译器并不把函数模板编译成一个可以处理任何数据类型的单一实体,而应该是编译器在实例化函数模板时根据类型实参从函数模板中产生一个真正的函数实体。(注:函数模板并不是一个函数实体,通过实例化产能产生真正的函数实体,函数模板可以认为是编译器生产函数实体的一个依据而已
  • 这种用具体数据类型替换函数模板类型形参的过程叫做实例化,这个过程产生一个函数模板的实例(函数实体)。
  • 只是使用函数模板,就会自动引发编译器实例化过程,因此程序员不需要额外地请求对函数模板的实例化

eg:functmpl04.cpp

#include <iostream>
using namespace std;

//函數模板(函數模板並不是一個函數)
template<class T>T Max(T x, T y){ 
    return x > y ? x : y;
}
/*
Max<int>等價
int Max(int x, int y){return x>y?x:y;}
 */
int main(void)
{
    int nx=10, ny=20;
    cout << Max<int>(nx, ny) << endl;
    //cout << Max(nx, ny) << endl;
    double dx=12.3, dy=45.6;
    cout << Max<double>(dx, dy) << endl;
    string sx="world", sy="hello";
    cout << Max<string>(sx, sy) << endl;

    return 0;
}

4、函数模板的扩展

  • 可以使用任何数据类型(基本类型和类类型)实例化函数模板
  • 但前提是这个数据类型必须支持函数模板所要执行的操作
    例如:一个不支持“>”运算符操作的类型,实例化Max函数模板,编译器将报错。

eg:functmpl04_02.cpp

#include <iostream>
using namespace std;

class Integer{
public:
    Integer(int const& i=0):m_i(i){}
    bool operator>(Integer const& that)const{
        return m_i > that.m_i;
    }
    friend ostream& operator<<(ostream& os, Integer const& that){
        return os << that.m_i;
    }
private:
    int m_i;
};

//函數模板(函數模板並不是一個函數)
template<class T>T Max(T x, T y){
    return x > y ? x : y;
}
/*
Max<int>等價
int Max(int x, int y){return x>y?x:y;}
 */
int main(void)
{
    int nx=10, ny=20;
    cout << Max<int>(nx, ny) << endl;
    //cout << Max(nx, ny) << endl;
    double dx=12.3, dy=45.6;
    cout << Max<double>(dx, dy) << endl;
    string sx="world", sy="hello";
    cout << Max<string>(sx, sy) << endl;
    Integer ix=100, iy=200;
    //在沒有重載>的時候下面的語句會報錯
    //functmpl04_02.cpp:13:11: error: no match for ‘operator>’ (operand types are ‘Integer’ and ‘Integer’)
    //重載>後就不會報錯
    cout << Max<Integer>(ix, iy) << endl;
    //Integer需要重載<<運算符
    return 0;
}

5、二次编译:编译器对模板都会进行两次编译

  • 第一次编译发生在实例化函数模板之前(产生真正函数实体之前),先检查模板本身内部代码,查看基本词法是否正确(例如:函数模板内部出现的所有标识符是否均有出处)对于已知类型的调用要检查调用是否有效,对于未知类型调用都合理
  • 第二次发生在实例化之后(产生真正函数实体之后),结合所有使用的类型实参,再次检查模板代码,查看所有调用是否均有效。

eg:05complie.cpp

#include <iostream>
using namespace std;

class Integer
{
public:
    void foo(){
        cout << "Integer::foo()" << endl;
    }   
    int m_i;
};

template<class T>void Max(){
    //一下都是第一次編譯
    //abcd;//亂寫的內容會報錯
    Integer i;//對已知類型的調用
    i.foo();//調用合理
    //i.abcd();//不合理的調用會報錯
    T t;//對未知類型的調用
    t.abcd();//調用合理,第二次不合理
    //t.ab<c>d();//出現括號也會報錯
}
int main(void)
{
    //函數模板實例化,第二次編譯,未知類型調用未知的調用會報錯
    Max<Integer>();
    return 0;
}

6、函数模板的隐式推断

  • 如果函数模板的调用形参类型形参相关
    例如:template<class T>T Max(T x, T y){...}
  • 那么在实例化函数模板时即使不显式指明函数模板的类型实参,编译器也有能力根据调用实参的类型隐式推断出正确的类型实参的类型
    例如:Max(123, 456)->Max<>(123, 456)->Max<int>(123, 456);
  • 获得和调用普通函数一致的语法表现形式

eg:06deduction.cpp

#include <iostream>
using namespace std;

class Integer{
public:
    Integer(int const& i=0):m_i(i){}
    bool operator>(Integer const& that)const{
        return m_i > that.m_i;
    }   
    friend ostream& operator<<(ostream& os, Integer const& that){
        return os << that.m_i;
    }   
private:
    int m_i;
};

//函數模板(函數模板並不是一個函數)
template<class T>T Max(T x, T y){ 
    return x > y ? x : y;
}
/*
Max<int>等價
int Max(int x, int y){return x>y?x:y;}
 */
int main(void)
{
    int nx=10, ny=20;
    cout << Max<>(nx, ny) << endl;
    //也可以寫成Max(nx, ny), 過程Max<>(nx, ny)==>Max<int>(nx, ny)
    double dx=12.3, dy=45.6;
    cout << Max<>(dx, dy) << endl;
    string sx="world", sy="hello";
    cout << Max<>(sx, sy) << endl;
    Integer ix=100, iy=200;
    //在沒有重載>的時候下面的語句會報錯
    //functmpl04_02.cpp:13:11: error: no match for ‘operator>’ (operand types are ‘Integer’ and ‘Integer’)
    //重載>後就不會報錯
    cout << Max<>(ix, iy) << endl;
    //Integer需要重載<<運算符
    return 0;
}

7、三种情况不能做隐式推断

  • 调用参数和类型参数不能完全相关
    eg:template<class T, class D>T Max(T x, T y){}
  • 隐式推断不支持隐式类型转换
    eg:template<class T>T Max(T x, T y){...}
    使用时:Max(123, 45.6);
  • 返回值类型不支持隐式推断

eg:06deduction_02.cpp

#include <iostream>
using namespace std;

class Integer{
public:
    Integer(int const& i=0):m_i(i){}
    bool operator>(Integer const& that)const{
        return m_i > that.m_i;
    }   
    friend ostream& operator<<(ostream& os, Integer const& that){
        return os << that.m_i;
    }   
private:
    int m_i;
};

template<class T>T Max(T x, T y){ 
    //調用行參和類型形參完全相關
    return x > y ? x : y;
}

template<class D, class T>void Foo(T x){ 
    //調用行參和類型形參不完全相關
}

template<class R, class T>R Bar(T x){ 
    R r;  
    return r;
}

int main(void)
{
    int nx=10, ny=20;
    cout << Max<>(nx, ny) << endl;
    //也可以寫成Max(nx, ny), 過程Max<>(nx, ny)==>Max<int>(nx, ny)
    double dx=12.3, dy=45.6;
    cout << Max<>(dx, dy) << endl;
    string sx="world", sy="hello";
    cout << Max<>(sx, sy) << endl;
    Integer ix=100, iy=200;
    cout << Max<>(ix, iy) << endl;
    
    //1)
    //Foo(nx);//報錯,不能隱式推斷
    Foo<double>(nx);//不報錯可以推斷T的類型是int,因爲顯式指定了D爲double
    
    //2)
    //Max(nx,dy);//報錯
    Max(nx,static_cast<int>(dy));//顯式轉換後不會報錯
    
    //3)
    //Bar(nx);//報錯,無法推斷返回值類型    
    Bar<double>(nx);//顯式給出R類型爲double

    return 0;
}

8、函数模板的重载

  • 普通函数和可实例化出该函数的函数模板构成重载关系。在数据类型匹配度相同情况下编译器优先选择普通函数。除非函数模板可以产生更好的数据类型匹配度的实例。
  • 函数模板的实例化不支持隐式类型转换但普通函数支持。在传递参数时如果需要编译器做隐式类型转换,则编译器选择普通函数。
  • 可以在实例化时用<>强行通知编译器选择函数模板。
  • 但是如果让编译器隐式推断类型,编译器让然坚持选择约束性较强的版本(即更特殊的版本)。

eg:07overload.cpp

#include <iostream>
using namespace std;

void Max(int x, int y)
{
    cout << "1:Max(int, int)" << endl;
}

template<class T>void Max(T x, T y)
{
    cout << "2:Max(T, T)" << endl;
}

template<class T>void Max(T* x, T* y)
{
    cout << "3:Max(T*, T*)" << endl;
}

int main(void)
{
    int nx=10, ny=20;
    double dx=12.3, dy=45.6;
    //1)
    Max(nx, ny);//選擇普通函數
    Max(dx, ny);//選擇函數模板
    //2)
    Max(nx, dy);//選擇普通函數
    //3)
    Max<>(nx, ny);//強行通知選擇模板
    //4)
    Max<>(&nx, &ny);//選擇模板2
    return 0;
}

三、类模板

1、类模板的定义

  • 在类模板内部类型实参可以想其他类型一样,用于成员变量,成员函数,成员类型(内部类),甚至基类声明.
    eg:
template<class A, class B>
class CMath{
public:
	A m_a;
	B func(){...};
};
  • 如果在类外实现成员函数:
template<class 类型参数1,...>
返回值类型 类模板名<类型形参1,...>::函数名(调用形参1,...){
	函数体实现;
}

例如:

template<class A, class B>B CMath<A, B>::func(){...;}

2、类模板的使用

  • 1)使用类模板必须对类模板进行实例化(产生真正的类)。类模板本身并不代表一个确定的类型(即不能用于定义对象),只有通过类型实例化成真正的类后才具备类的语义(即可以定义对象)。

eg:08clstemplate.cpp

#include <iostream>
using namespace std;

//類模板(並非真正的類)
template<class T>
class CMath
{
public:
    CMath(T const& t1, T const& t2):m_t1(t1), m_t2(t2){}
    T sum(){
        return m_t1 + m_t2;
    }   
private:
    T m_t1;
    T m_t2;
};
//實例化的原理
//class CMatn<int>{...}
int main(void)
{
    int nx=10, ny=20;
    //實例化類模板
    CMath<int> math1(nx, ny);
    cout << math1.sum() << endl;
    double dx=12.3, dy=45.6;
    CMath<double> math2(dx, dy);
    cout << math2.sum() << endl;
    string sx="hello ", sy="world";
    CMath<string> math3(sx, sy);
    cout << math3.sum() << endl;
    return 0;
}
  • 2)类模板被实例化时类模板中的成员函数并没有实例化,成员函数只是被调用时才会被实例化(即产生真正成员函数)
    注: 成员虚函数除外

    • 某些类型虽然并没有提供类模板所需要的全部功能但照样可以实例化类模板,只要不调用那些未提供功能的成员函数即可
//上面的代码
//当编译器看到CMath<int>时,生成下面的累,只有成员变量,没有成员函数
class CMath<int>{
	public:
	private:
		int m_t1;
		int m_t2;
};

//当看到math1时生成构造函数,并执行构造函数
class CMath<int>{
	public:
		CMath(int const& t1, int const& t2) : m_t1(t1), m_t2(t2){}
	private:
		int m_t1;
		int m_t2;
};
//当调用sum函数才实例化sum函数
class CMath<int>{
	public:
		CMath(int const& t1, int const& t2) : m_t1(t1), m_t2(t2){}
		int sum(void){
			return m_t1 + m_t2;
		}
	private:
		int m_t1;
		int m_t2;
};
#include <iostream>

using namespace std;

class Integer{
        public:
                Integer(int i) : m_i(i){}
                /*重载+操作符
                Integer operater+(const Integer& that)const{
                        return m_i + that.m_i;
                }
                */
        private:
                int m_i;
};

template<class T>
class CMath{
        public:
                CMath(T const& t1, T const& t2): m_t1(t1), m_t2(t2){}
                T sum(void){
                        return m_t1 + m_t2;
                }   
        private:
                T m_t1;
                T m_t2;
};
int main(void)
{
        Integer ix = 100;
        Integer iy = 200;

        //可以使用类Integer实例化类模板CMath
        CMath<Integer> math(ix, iy);
        //但不能调用sum函数,因为Integer类不支持加法操作
        //所以想要支持加法操作,需要重载+操作符
        math.sum();//error
        return 0;
}                                                                                                      
  • 3)类模板的类型实参不支持隐式推断

eg:08clstemplate_02.cpp

#include <iostream>
using namespace std;

class Integer
{
public:
    Integer(int const& i):m_i(i){}

    //重載運算符+ <<
    /*
    Integer operator+(Ineger const& that){
        return m_i + thar.m_i;
    }
    friend ostream& operator<<(ostream& os, const& i){
        return os << i.m_i;
    }
    */
private:
    int m_i;
};

template<class T>
class CMath
{
public:
    CMath(T const& t1, T const& t2):m_t1(t1), m_t2(t2){}
    T sum(){
        return m_t1 + m_t2;
    }
private:
    T m_t1;
    T m_t2;
};

int main(void)
{
    int nx=10, ny=20;
    CMath<int> math1(nx, ny);//調用構造函數時才實例化構造函數
    math1.sum();//調用sum()函數才實例化sum函數
    Integer ix=100, iy=200;

    //Integer沒有滿足類模板提供的加法功能,但是還是能使用類模板實例化
    CMath<Integer> math2(ix, iy);
    //math2.sum();//報錯Integer不支持加法功能,只能重載+運算符後才不報錯
    //cout << math2.sum() << endl;//需要重載<<運算符

    //CMath<> math3(nx, ny);//報錯,不能隱式推斷類模板的類型實參
    return 0;
}

3、类模板的静态成员

  • 类模板中的静态成员既不是每个对象拥有一份,也不是类模板拥有一份,而应该是由类模板实例化出的每一个真正的类各有一份,且为该实例化定义的所有对象共享

eg:09static.cpp

#include <iostream>
using namespace std;

template<class T>
class CMath
{
public:
    static void print(){
        cout << "&m_i:" << &m_i << ",&m_t:" << &m_t << endl;
    }   
private:
    static int m_i;
    static T m_t;
};

//靜態成員初始化(這裏暫時不給初值,後面講)
template<class T>int CMath<T>::m_i;
template<class T>T CMath<T>::m_t;

int main(void)
{
    CMath<int> a, b;
    a.print();
    b.print();
    CMath<int>::print();
    
    CMath<double> c, d;
    c.print();
    d.print();
    CMath<double>::print();

    return 0;
}

在这里插入图片描述

4、类模板的递归实例化

  • 可以使用任何类型来实例化类模板,只要这个类型提供了类模板所需要的功能。
  • 类模板实例化所产生的类也可以用来实例化模板自身,这种做法称之为类模板的递归实例化。
  • 通过这种方法可以构建空间上具有递归特性的数据结构(例如:多维数组)

eg:10recursion.cpp

#include <iostream>
using namespace std;

template<class T>
class Arrary
{
public:
    T& operator[](size_t i){ 
        return m_arr[i];
    }   
private:
    T m_arr[10];
};

int main(void)
{
    Arrary<int> a;
    for(size_t i=0; i<10; i++){
        a[i] = i+1;
    }   
    for(size_t i=0; i<10; i++){
        cout << a[i] << ' ';
    }   
    cout << endl;

    //遞歸實例化
    Arrary<Arrary<int> > b;//注意不> >中間要有空格,否則編譯器認爲是>>
    for(size_t i=0; i<10; i++){
        for(size_t j=0; j<10; j++){
            b[i][j] = i + j;
        }
    }   
    for(size_t i=0; i<10; i++){
        for(size_t j=0; j<10; j++){
            cout << b[i][j] << '\t';
        }
        cout << endl;
    }   

    return 0;
}

在这里插入图片描述

5、类模板的特化

  • 全局特化:包括全类特化和成员特化
    • 全类特化:特化一个类模板可以特化该类模板所有的成员函数,相当于重新写了一个针对某种特定数据类型的具体类
      • 声明形式:template<>class 类模板名 <类型参数1,...>{...};
        eg:template<>class CMath <char*>{...}
    • 成员特化:类模板特化除了可以对整个类进行特化以外,还可以只针对某个部分成员函数进行特化
      • 声明形式:tamplate<> 返回值类型 类模板名<类型参数1,...>::成员函数名(调用参数1,...){...}
        eg:template<> char* const CMath<char* const>::sum(..){...}
  • 局部特化:类模板的局部特化,除非必要,否则尽量不要特化,因为特化版本过多容易引发编译器匹配歧义。

eg:11special.cpp(全类特化)

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

template<class T>class CMath
{
public:
    CMath(T const& t1, T const& t2):m_t1(t1), m_t2(t2){}
    T sum(){
        return m_t1 + m_t2;
    }
private:
    T m_t1;
    T m_t2;
};
//全類特化
template<>class CMath<char* const>
{
public:
    CMath(char* const& t1, char* const& t2):m_t1(t1), m_t2(t2){}
    char* const sum(){
        return strcat(m_t1, m_t2);
    }
private:
    char* const m_t1;
    char* const m_t2;
};
int main()
{
    int nx=10, ny=20;
    CMath<int> m1(nx, ny);
    cout << m1.sum() << endl;

    string sx="hello", sy="world";
    CMath<string> m2(sx, sy);
    cout << m2.sum() << endl;

    char cx[256]="hello", cy[256]="world";
    CMath<char* const> m3(cx, cy);
    cout << m3.sum() << endl;
    return 0;
}

在这里插入图片描述

eg:11special_02.cpp

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

template<class T>class CMath
{
public:
    CMath(T const& t1, T const& t2):m_t1(t1), m_t2(t2){}
    T sum(){
        return m_t1 + m_t2;
    }   
private:
    T m_t1;
    T m_t2;
};

//成員特化
template<>char* const CMath<char* const>::sum()
{
    return strcat(m_t1, m_t2);
}
//全類特化
/*
template<>class CMath<char* const>
{
public:
    CMath(char* const& t1, char* const& t2):m_t1(t1), m_t2(t2){}
    char* const sum(){
        return strcat(m_t1, m_t2);
    }
private:
    char* const m_t1;
    char* const m_t2;
};
*/

int main()
{
    int nx=10, ny=20;
    CMath<int> m1(nx, ny);
    cout << m1.sum() << endl;

    string sx="hello", sy="world";
    CMath<string> m2(sx, sy);
    cout << m2.sum() << endl;

    char cx[256]="hello", cy[256]="world";
    CMath<char* const> m3(cx, cy);
    cout << m3.sum() << endl;
    return 0;
}

在这里插入图片描述

eg:12partspecial.cpp(局部特化)

#include <iostream>
using namespace std;

template<class T1, class T2>class CMath
{
public:
    static void foo(){
        cout << "1:CMath<T1, T2>" << endl;
    }   
};
//局部特化
template<class T1>class CMath<T1, short>
{
public:
    static void foo(){
        cout << "2:CMath<T1, short>" << endl;
    }   
};

template<class T>class CMath<T, T>
{
public:
    static void foo(){
        cout << "3:CMath<T, T>" << endl;
    }   
};

template<class T1, class T2>class CMath<T1*, T2*>
{
public:
    static void foo(){
        cout << "4:CMath<T*, T*>" << endl;
    }   
};

int main(void)
{
    CMath<int, double>::foo();
    CMath<int, short>::foo();
    //CMath<short, short>::foo();//?沒法選擇, 會報錯
    CMath<int*, double*>::foo();
    //CMath<int*, int*>::foo();//?沒法選擇,會報錯
    return 0;
}

在这里插入图片描述

6、类模板类型参数缺省值

  • 1)类模板的类型参数可以带缺省值
    实例化类模板时,如果提供了模板的类型实参则用所提供的类型实参来实例化类模板,如果没有提供模板类型实参则用相应的模板形参的缺省类型来实例化模板。
  • 2)如果模板的某个类型形参带有缺省值,那么它后面的模板形参都必须带有缺省值。

eg:13default.cpp

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

template<class T, class D=short>class CMath
{
public:
    void print(){
        cout << "m_t:" << typeid(m_t).name() <<  
            ", m_d:" << typeid(m_d).name() << endl;
    }   
private:
    T m_t;
    D m_d;
};

int main(void)
{
    CMath<int, double> m;
    m.print();
    CMath<int> m2; 
    m2.print();

    return 0;
}

在这里插入图片描述

7、类模板的数值型模板参数

  • 数值形式的模板参数:类模板的模板参数并不限于类型参数,普通数值也可以作为模板的参数。

eg:14valparam.cpp

#include <iostream>
using namespace std;

template<class T, size_t S=10>class Arrary
{
public:
    T& operator[](size_t i){ 
        return m_arr[i];
    }   
    size_t size(){
        return S;
    }   
private:
    T m_arr[S];
};
int main(void)
{
    //Arrary<int> a;
    Arrary<int, 5> a;
    for(size_t i=0; i<a.size(); i++){
        a[i] = i+1;
    }   
    for(size_t i=0; i<a.size(); i++){
        cout << a[i] << ' ';
    }   
    cout << endl;

    return 0;
}

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值