文中例程是本人自己理解和看网页的例子整理出来的,如有错误麻烦及时指正,水平有限,望与各位多多交流
这里简单说一下关于类的声明和类模板的声明,主要是对cppreference里面内容的一部分说明
class-key //类关键字
class-head-name //类名称,可选限定和final
base-clause //基类列表
member-specification//成员
对于一个类声明首先要考虑两个情况
普通前置声明(优先)
详细类型指定符引入(注意和块内覆盖声明区分)
(这里顺带提一下详细类型指定符引入吧,详细指定符引入实际上就是在没有前置声明的情况下, 并且当前标识符没有被占用时用一个详细的class-key来声明并使用这个成名的类的一个机制)
例:
class cA;
namespace N11
{
class cA func(class cB);//::cA,声明N11::cB
cB *s;
}
class cA{};
class N11::cB{};
cA N11::func(class N11::cB)
{
cA S;//::cA
class cA;//覆盖cA声明
int i = 0;
class CA{};
return S;
}
定义一个类这里和之前的声明的声明器同,使用的是member-declarator-list,不同点在于这里可以使用位域,春指定符,override,final,和default还有delete等
对于定义和声明一个成员函数,对于定义而言,花括号后面的分号可选(实际上被处理为一条空语句)
其中要注意的是一个叫做static_assert的一个东西,这个东西我估计主要是用于判断模板生成是否成功的,因为这个同assert不同,这个是在编译期会抛出error的
template<typename args>
struct is_float_t;
template<typename _Ty,_Ty Value>
struct is_true_bool
{
static constexpr _Ty value = Value;
};
template<>
struct is_float_t<double>:is_true_bool<bool,1>{};
template<>
struct is_float_t<float> :is_true_bool<bool, 1>{};
template<>
struct is_float_t<long double> :is_true_bool<bool, 1>{};
template<typename args>
struct is_float_t:is_true_bool<bool, 0>{};
template<typename _Ty>
struct is_float :is_float_t<_Ty>{};
template<typename _Ty>
/*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-*/
struct cA
{
static_assert(is_float<_Ty>::value, "Type Is Not Float");
};
int main()
{
cA<float> s;
cA<int> ss; //error
return 0;
}
类模板形式其实很平时的:
templatelist>class-declaration
export templatelist>class-declaration
但是看似简单,其实里面还是蛮讲究的, 其中类模板的特例化和部分特例化就值得很注意,对于一个特例化和部分特例化而言其中的模板参数要看属于哪一种,并且会要求在对应的类型声明器后面加上相应的参数补充等
template<typename... args>
struct is_float_t;
template<typename _Ty,_Ty Value>
struct is_true_bool
{
static constexpr _Ty value = Value;
};
template<>
struct is_float_t<double>:is_true_bool<bool,1>{};
template<>
struct is_float_t<float> :is_true_bool<bool, 1>{};
template<>
struct is_float_t<long double> :is_true_bool<bool, 1>{};
template<typename... args>
struct is_float_t:is_true_bool<bool, 0>{};
template<typename _Ty>
struct is_float :is_float_t<_Ty>{};
template<typename _Ty>
struct cA
{
static_assert(is_float<_Ty>::value, "Type Is Not Float");
};
template<typename ...args>
class val_case;
template<>
class val_case<> //递归终止点
{
public:
val_case() = default;
};
template<typename _Ty, typename... args>
class val_case<_Ty,args...>:public val_case
{
public:
template<typename _ty,typename... Args>
val_case(_ty num, Args... arg) :val_case(arg...), member(num)
{}
private:
_Ty member;
};
综合以上可以发现,对于一个声明如果是单独的特例化的话是不需要对之后定义的类进行特殊的说明的,但是如果是部分特例化的话,我们需要对之后的类名称后面加上部分特例化的“部分”部分,就比如:
template <typename _Ty,typename _Ty1>
class N11
{
};
template
class N11<int, int>; //特例化
template <typename _Ty>
class N11<_Ty, int> //偏特例化,省略了_Ty1,因为类型已知
{};
template <typename _Ty,typename _Ty1>
class N11<_Ty *, _Ty1 *> //偏特例化,都没有省略
{
public:
N11(){}
};
template<typename _Ty> class T1
{
public:
T1();
virtual ~T1();
};
template<typename _Ty>T1<_Ty>::T1()
{
}
template<typename _Ty>T1<_Ty>::~T1()
{
}
template T1<double>::T1()
{
std::cout<<"special"<<std::endl;
}