使用模版元编程实现C和C++中复杂类型声明的语义化

背景

C和C++中提供的基本类型总共有13中,定义在limit头文件中。如下:

//整数类型
bool
char | signed char | unsigned char
short | unsigned short
int | unsigned int
long | unsigned long

//浮点类型
float
double
long double

除此之外,C++还定义了两种新的长整数类型:

long long | unsigned long long

针对这些基本类型,然后使用复合类型进行组合,会得到很多复杂的声明式。复合类型有:

[] //数组
*  //指针
&  //引用
() //函数
const //常量修饰

对于理解复杂声明需要深入理解各个复合运算的规则,这是一种较难入手学习的点,这里使用模版元编程的技术,充分利用编译器对复杂声明进行的计算过程,得出每个复杂声明的语义化描述,不仅能加深对编译器解析复杂声明的理解,也能练习模版元编程的技术。

实现

使用一个type_descriptor的模版类来实现,对于基本类型使用全特化版本输出,对于复杂类型使用偏特化进行实现。源码如下:

#include <iostream> 

template<typename T>
struct type_descriptor
{
    type_descriptor(){}
};

//fully specialization
template<>
struct type_descriptor<bool>
{
    type_descriptor(){ std::cout << "bool"; }
};
template<>
struct type_descriptor<char>
{
    type_descriptor(){ std::cout << "char"; }
};
template<>
struct type_descriptor<unsigned char>
{
    type_descriptor(){ std::cout << "unsigned char"; }
};
template<>
struct type_descriptor<signed char>
{
    type_descriptor(){ std::cout << "signed char"; }
};
template<>
struct type_descriptor<int>
{
    type_descriptor(){ std::cout << "int"; }
};
template<>
struct type_descriptor<unsigned int>
{
    type_descriptor(){ std::cout << "unsigned int"; }
};
template<>
struct type_descriptor<long>
{
    type_descriptor(){ std::cout << "long"; }
};
template<>
struct type_descriptor<unsigned long>
{
    type_descriptor(){ std::cout << "unsigned long"; }
};
template<>
struct type_descriptor<long long>
{
    type_descriptor(){ std::cout << "long long"; }
};
template<>
struct type_descriptor<unsigned long long>
{
    type_descriptor(){ std::cout << "unsigned long long"; }
};
template<>
struct type_descriptor<float>
{
    type_descriptor(){ std::cout << "float"; }
};
template<>
struct type_descriptor<double>
{
    type_descriptor(){ std::cout << "double"; }
};
template<>
struct type_descriptor<long double>
{
    type_descriptor(){ std::cout << "long double"; }
};


//partial specialization
template<typename T>
struct type_descriptor<T*>
{
    type_descriptor()
    {
       std::cout << "pointer to ";
       type_descriptor<T>();
    }
};
template<typename T>
struct type_descriptor<T&> {
    type_descriptor()
    {
        std::cout << "reference of ";
        type_descriptor<T>();
    }
};
template<typename T>
struct type_descriptor<const T>
{
    type_descriptor()
    {
        std::cout << "const ";
        type_descriptor<T>();
    }
};
template<typename T>
struct type_descriptor<T[]>
{
    type_descriptor()
    {
        std::cout << "array of ";
        type_descriptor<T>();
    }
};
template<typename T>
struct type_descriptor<T()>
{
    type_descriptor()
    {
        std::cout << "function returning ";
        type_descriptor<T>();
    }
};

测试代码如下:

int main(int argc, char ** argv)
{
    type_descriptor<char*>();
    std::cout << '\n';
    type_descriptor<char * &>();
    std::cout << '\n';
    type_descriptor<double const * const(*[])()>();
    std::cout << '\n';
    return 0;
}

测试的三个声明中逐渐复杂,第一个是指针char *,第二个是指针的引用char * &,但是第三个声明就很复杂了,这个复杂的声明需要编译器去解析,熟悉这个过程的朋友肯定知道,先从内往外一层层来解析。下面是运行结果:

pointer to char
reference of pointer to char
array of pointer to function returning const pointer to const double

对于不熟悉第三复杂声明的解析过程的朋友,可以很容易从上述运行结果中看出来,这个声明本质上是一个数组,数组中每个元素都是一个指向函数的指针,每个函数返回的是一个double类型的常量指针并且这个返回的指针本身也是一个常量(const pointer to const double)。
有需要的朋友可以拿去一用~_~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值