C++学习 之 模板

C++是一种两层次语言。

C++的模板设计之初是为了实现泛型编程,但后来发现模板的能力远不止泛型编程,C++模板是图灵完备的,理论上来说C++模板可以执行任何计算任务,但因为模板是编译期间计算的,其能力受编译器实现的限制,因而衍生出模板元编程。

动态代码

C++执行期间的代码称为动态代码,动态代码就不多介绍。

静态代码

C++执行编译计算的代码称为静态代码,静态代码由模板元编程和预处理的宏组成,预处理的宏也能进行部分编程,因而称为宏元编程。
模版元编程举例:

template<typename T, int i=1>
class someComputing {
public:
    typedef volatile T* retType; // 类型计算
    enum { retValume = i + someComputing<T, i-1>::retValume }; // 数值计算,递归
    static void f() { std::cout << "someComputing: i=" << i << '\n'; }
};
template<typename T> // 模板特例,递归终止条件
class someComputing<T, 0> {
public:
    enum { retValume = 0 };
};

模版元编程的控制结构:
条件 if 语句:

// 通例为空,若不匹配特例将报错,很好的调试手段(这里是 bool 就无所谓了)
template<bool c, typename Then, typename Else> class IF_ { };
template<typename Then, typename Else>
class IF_<true, Then, Else> { public: typedef Then reType; };
template<typename Then, typename Else>
class IF_<false,Then, Else> { public: typedef Else reType; };

IF_<> 的使用示例

const int len = 4;
typedef
    IF_<sizeof(short)==len, short,
    IF_<sizeof(int)==len, int,
    IF_<sizeof(long)==len, long,
    IF_<sizeof(long long)==len, long long,
    void>::reType>::reType>::reType>::reType
int_my; // 定义一个指定字节数的类型
std::cout << sizeof(int_my) << '\n';

while 语句:

// 隐含要求: Condition 返回值 ret,Statement 有类型 Next
template<template<typename> class Condition, typename Statement>
class WHILE_ {
    template<typename Statement> class STOP { public: typedef Statement reType; };
public:
    typedef typename
        IF_<Condition<Statement>::ret,
        WHILE_<Condition, typename Statement::Next>,
        STOP<Statement>>::reType::reType
    reType;
};

WHILE_<> 的使用示例

// 计算 1^e+2^e+...+n^e
template<int n, int e>
class sum_pow {
    template<int i, int e> class pow_e{ public: enum{ ret=i*pow_e<i,e-1>::ret }; };
    template<int i> class pow_e<i,0>{ public: enum{ ret=1 }; };
    // 计算 i^e,嵌套类使得能够定义嵌套模板元函数,private 访问控制隐藏实现细节
    template<int i> class pow{ public: enum{ ret=pow_e<i,e>::ret }; };
    template<typename stat>
    class cond { public: enum{ ret=(stat::ri<=n) }; };
    template<int i, int sum>
    class stat { public: typedef stat<i+1, sum+pow<i>::ret> Next;
                         enum{ ri=i, ret=sum }; };
public:
    enum{ ret = WHILE_<cond, stat<1,0>>::reType::ret };
};

int main() {
    std::cout << sum_pow<10, 2>::ret << '\n';
    std::cin.get(); return 0;
}

借鉴总结

  1. C++ 模板包括函数模板和类模板,模板参数形式有:类型、模板型、非类型(整型、指针);
  2. 模板的特例化分完全特例化和部分特例化,实例将匹配参数集合最小的特例;
  3. 用实例参数替换模板形式参数称为实例化,实例化的结果是产生具体类型(类模板)或函数(函数模板),同一模板实参完全等价将产生等价的实例类型或函数;
  4. 模板一般在头文件中定义,可能被包含多次,编译和链接时会消除等价模板实例;
  5. template、typename、this 关键字用来消除歧义,避免编译错误或产生不符预期的结果;
  6. C++11 对模板引入了新特性:“>>”、函数模板也可以有默认参数、变长模板参数、外部模板实例(extern),并弃用 export template;
  7. C++ 模板是图灵完备的,模板编程是函数编程风格,特点是:没有可变的存储、递归,以“<>”为输入,typedef 或静态常量为输出;
  8. 编译期数值计算虽然实际意义不大,但可以很好证明 C++ 模板的能力,可以用模板实现类似普通程序中的 if 和 while 语句;
  9. 一个实际应用是循环展开,虽然编译器可以自动循环展开,但我们可以让这一切更可控;
  10. C++ 模板编程的两个问题是:难调试,会产生冗长且难以阅读的编译错误信息、代码膨胀(源代码膨胀、二进制对象文件膨胀),改进的方法是:增加一些检查代码,让编译器及时报错,使用特性、策略等让模板更通用,可能的话合并一些模板实例(如将代码提出去做成单独模板);
  11. 表达式模板和向量计算是另一个可加速程序的例子,它们将计算表达式编码到类型,这是通过模板嵌套参数实现的;
  12. 特性,策略,标签是模板编程常用技巧,它们可以是模板变得更加通用;
  13. 模板甚至可以获得类型的内部信息(是否有某个 typedef),这是反射中的内省,C++ 在语言层面对反射支持很少(typeid),这不利于模板元编程;
  14. 可以用递归实现伪变长参数模板,C++11 变长参数模板背后的原理也是模板递归;
  15. 元容器存储元信息(如类型)、类型过滤过滤某些类型,它们是元编程的高级特性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值