模板的报错不准确
1)- 模板函数
假设现在要实现一个比较两个数是否相等的重载函数。
#include
#include
#include
using namespace std;
template<class T>
void Swap(T* x1, T* x2)
{
T x = *x1;
*x1 = *x2;
*x2 = x;
}
int main()
{
int a = 1, b = 2;
Swap(&a, &b);
int *p1 = &a;
int *p2 = &b;
Swap(&p1, &p2);
char c1 = 1, c2 = 2;
Swap(&c1, &c2);
system("pause");
return 0;
}
第一组交换前:
第一组交换后:
第二组交换前:
第二组交换后:
void Swap(T* *x1, T** x2)
{
T x = **x1;
**x1 = **x2;
**x2 = x;
}
函数模板格式:
template1,class形参名2,class形参名n>
返回类型 函数名(参数列表)
{...}
不同的函数推演出不同的模板类型,底层调用的是三个不同的函数类型。
模板函数只有被推演出来是什么类型才参与编译,否则不参与编译。没有被推演出来的话,它只检查函数的外壳即函数名哪一行,函数内部不检查。
“`
本质是模板推演出的函数构成重载
template<typename T>
bool IsEqual(const T& left, const T& right)
{
return left == right;
}
template <typename T1,class T2>
bool IsEqual(const T1& left, const T2& right)
{
return left == right;
}
bool IsEqual(const int& left, const int& right)
{
return left == right;
}
int main()
{
/*string s1("s1");
string s2("s2");*/
cout << IsEqual(1, 2) << endl;
cout << IsEqual(1.2,1) << endl;
cout << IsEqual(1.2, 1) << endl;
cout << IsEqual<int>(1.2, 1) << endl;
system("pause");
return 0;
}
类模板的格式
template1, class 形参名2, ...class 形参名n>
class 类名 { ... };
模板类实现动态顺序表:
https://mp.csdn.net/mdeditor/80299402
template <typename T>
class SeqList
{
private :
int _size ;
int _capacity ;
T* _data ;
};
// template
template <class T, class Container = SeqList //缺省参数
class Stack
{
public :
void Push (const T& x );
void Pop ();
const T & Top();
bool Empty ();
private :
Container _con ;
};
void Test ()
{
Stack<int > s1;
Stack<int , SeqList< int>> s2 ;
}
template<typename T,size_t MAX_SIZE=10>//带缺省模板参数
class SeqList
{
public:
SeqList();
private:
T_array[MAX_SIZE];
int _size;
};
template<typename T,size_t MAX_SIZE>
SeqList::SeqList()
:_size(0)
{}
void Test()
{
SeqList<int>s1;
SeqList<int, 20>s2;
}
图解:
扩展 面试题:
不要使用循环 */,实现1+2+3+…+n
1、实现 不要求
2、实现哦 o(1)–非类型模板参数
cout<<typeid(T).name()<
类型萃取:RTTI
1、T->int char double… 内置类型 memcpy
2、T->string… 自定义类型类型 for+operator=
RTTI:程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。
代码:
1、特化之前:
template<class T>
class SeqList
{
public:
void Expand()
{
cout << "for+operator=" << endl;
}
};
int main()
{
SeqList<int> s1;
s1.Expand();
SeqList<string> s2;
s2.Expand();
system("pause");
return 0;
}
运行结果:
分析:
调用的全是for+operator=
2、特化:
代码:
template<>
class SeqList<int>
{
public:
void Expand()
{
cout << "memcpy" << endl;
}
};
代码:
template < typename T1,typename T2>
class Data
{
public:
Data()
{
cout << "" << endl;
}
private:
T1 _d1;
T2 _d2;
};
template<>
class Data<int,int>
{
public:
Data()
{
cout << "" << endl;
}
private:
int _d1;
int _d2;
};
int main()
{
Data<int, int>d1;
Data<int, char>d2;
system("pause");
return 0;
}
偏特化:
代码;
template<class T>
class SeqList
{
public:
void Expand()
{
cout << "for+operator=" << endl;
}
};
template < typename T1,typename T2>
class Data
{
public:
Data()
{
cout << "" << endl;
}
private:
//T1 _d1;
//T2 _d2;
};
//全特化
template<>
class Data<int,int>
{
public:
Data()
{
cout << "" << endl;
}
private:
int _d1;
int _d2;
};
//偏特化
template<class T1>
class Dataint>
{
public:
Data()
{
cout << "" << endl;
}
private:
int _d1;
int _d2;
};
//偏特化(指针类型)
template<typename T1,typename T2>
class Data
{
public:
Data()
{
cout << "" << endl;
}
private:
};
//偏特化(引用类型)
template<typename T1, typename T2>
class Data
{
public:
Data()
{
cout << "" << endl;
}
private:
};
////偏特化(引用类型)
//template
//class Data
//{
//public:
// Data()
// {
// cout << "" << endl;
// }
//private:
//
//};
int main()
{
Data<int, int>d1;
Data<int, char>d2;
Data<char, int>d3;
Data<int*, int*>d4;
Data<char&, int&>d5;
Data<char*, int&>d6;
system("pause");
return 0;
}
#include
using namespace std;
#include
#include
struct __TrueType
{};
struct __FalseType
{};
template < class T>
struct TypeTraits
{
typedef __FalseType IsPodType;
};
template<>
struct TypeTraits<int>
{
typedef __TrueType IsPodType;
};
template<class T>
T* __TypeCopy(const T* src, T* dst, size_t n,__TrueType)
{
cout << "memcpy" << endl;
return (T*)memcpy(dst, src, sizeof(T)*n);
}
template<class T>
T* __TypeCopy(const T* src, T* dst, size_t n,__FalseType)
{
for (size_t i = 0; i < n; i++)
{
dst[i] = src[i];
}
cout << "for+operator=" << endl;
return dst;
}
template<class T>
T* TypeCopy(const T* src, T* dst, size_t n)
{
return __TypeCopy(src, dst, n,TypeTraits::IsPodType());
}
void TestCopy()
{
int srcint[3] = { 1, 2, 3 };
int dstint[3] = { 0 };
string srcstring[3] = { "11", "22", "33" };
string dststring[3];
TypeCopy(srcint, dstint, 3);
TypeCopy(srcstring, dststring, 3);
}
int main()
{
TestCopy();
system("pause");
return 0;
}
运行截图:
int 型:
图解:
总结:
1、偏特化并不仅仅是指特殊部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本
2、模板的全特化和偏特化都是在已定义的模板基础之上,不能单独存在。
分离编译不会模板实例化
1)显示实例化,最好指定模板类型(因为有的模板必须指定类型)。
2)最好的方式是把声明和定义放一个头文件里(类里面定义太大了)。
优点:
缺点:
1、模版让代码变得凌乱复杂,不易维护,编译代码时间变长。
2、出现模板编译错误时,错误信息非常凌乱,不易定位错误。