设为首页 加入收藏

TOP

C++11模版元编程(一)
2015-11-21 01:03:04 来源: 作者: 【 】 浏览:6
Tags:模版 编程
1.概述
?
  模版元 编程(template metaprogram)是C++中最复杂也是威力最强大的编程范式,它是一种可以创建和操纵程序的程序。模版元编程完全不同于普通的运行期程序,它很独特,因为模版元程序的执行完全是在编译期,并且模版元程序操纵的数据不能是运行时变量,只能是编译期常量,不可修改,另外它用到的语法元素也是相当有限,不能使用运行期的一些语法,比如if-else,for等语句都不能用。因此,模版元编程需要很多技巧,常常需要类型重定义、枚举常量、继承、模板偏特化等方法来配合,因此编写模版元编程比较复杂也比较困难。
?
  现在C++11新增了一些模版元相关的特性,不仅可以让我们编写模版元程序变得更容易,还进一步增强了泛型编程的能力,比如type_traits让我们不必再重复发明轮子了,给我们提供了大量便利的元函数,还提供了可变模板参数和tuple,让模版元编程“如虎添翼”。本文将向读者展示C++11中模版元编程常用的技巧和具体应用。
?
2.模版元基本概念
?
  模版元程序由元数据和元函数组成,元数据就是元编程可以操作的数据,即C++编译器在编译期可以操作的数据。元数据不是运行期变量,只能是编译期常量,不能修改,常见的元数据有enum枚举常量、静态常量、基本类型和自定义类型等。
?
  元函数是模板元编程中用于操作处理元数据的“构件”,可以在编译期被“调用”,因为它的功能和形式和运行时的函数类似,而被称为元函数,它是元编程中最重要的构件。元函数实际上表现为C++的一个类、模板类或模板函数,它的通常形式如下:
?
template
struct meta_func
{
? ? static const value = N+M;
}
  调用元函数获取value值:cout<::value<
?
  meta_func的执行过程是在编译期完成的,实际执行程序时,是没有计算动作而是直接使用编译期的计算结果的。元函数只处理元数据,元数据是编译期常量和类型,所以下面的代码是编译不过的:
?
int i = 1, j = 2;
meta_func::value; //错误,元函数无法处理运行时普通数据
  模板元编程产生的源程序是在编译期执行的程序,因此它首先要遵循C++和模板的语法,但是它操作的对象不是运行时普通的变量,因此不能使用运行时的C++关键字(如if、else、for),可用的语法元素相当有限,最常用的是:
?
enum、static const,用来定义编译期的整数常量;
typedef/using,用于定义元数据;
T、Args...,声明元数据类型;
template,主要用于定义元函数;
"::",域运算符,用于解析类型作用域获取计算结果(元数据)。
如果模板元编程中需要if-else、for等逻辑时该怎么办呢?
?
模板元中的if-else可以通过type_traits来实现,它不仅仅可以在编译期做判断,还可以做计算、查询、转换和选择。
?
模板元中的for等逻辑可以通过递归、重载、和模板特化(偏特化)等方法实现。
?
下面来看看C++11提供的模版元基础库type_traits。
?
3.type_traits
?
  type_traits是C++11提供的模板元基础库,通过type_traits可以实现在编译期计算、查询、判断、转换和选择,提供了模板元编程需要的一些常用元函数。下面来看看一些基本的type_traits的基本用法。
?
  最简单的一个type_traits是定义编译期常量的元函数integral_constant,它的定义如下:
?
template< class T, T v >
struct integral_constant;
  借助这个简单的trait,我们可以很方便地定义编译期常量,比如定义一个值为1的int常量可以这样定义:
?
using one_type = std::integral_constant;
或者
?
template
struct one_type : std::integral_constant{};
  获取常量则通过one_type::value来获取,这种定义编译期常量的方式相比C++98/03要简单,在C++98/03中定义编译期常量一般是这样定义的:
?
?
template
struct one_type
{
? ? enum{value = 1};
};
?
template
struct one_type
{
? ? static const int value = 1;
};
?
  可以看到,通过C++11的type_traits提供的一个简单的integral_constant就可以很方便的定义编译期常量,而无需再去通过定义enum和static const变量方式去定义编译期常量了,这也为定义编译期常量提供了另外一种方法。C++11的type_traits已经提供了编译期的true和false,是通过integral_constant来定义的:
?
typedef ?integral_constant true_type;
typedef ?integral_constant false_type;
  除了这些基本的元函数之外,type_traits还提供了丰富的元函数,比如用于编译期判断的元函数:
?
?
?
  这只是列举一小部分的type_traits元函数,type_traits提供了上百个方便的元函数,读者可以参考http://en.cppreference.com/w/cpp/header/type_traits,这些基本的元函数用法比较简单:
?
?
#include
#include
?
int main() {
? std::cout << "int: " << std::is_const::value << std::endl;
? std::cout << "const int: " << std::is_const::value << std::endl;
?
? //判断类型是否相同
? std::cout<< std::is_same::value<<"\n";// true
? std::cout<< std::is_same::value<<"\n";// false
?
? //添加、移除const
? cout << std::is_same::type>::value << endl;
? cout << std::is_same::type>::value << endl;
?
? //添加引用
? cout << std::is_same::type>::value << endl;
? cout << std::is_same::type>::value << endl;
?
? //取公共类型
? typedef std::common_type::type NumericType;
? cout << std::is_same::value << endl;
?
? return 0;
}
?
  type_traits还提供了编译期选择traits:std::conditional,它在编译期根据一个判断式选择两个类型中的一个,和条件表达式的语义类似,类似于一个三元表达式。它的原型是:
?
template< bool B, class T, class F >
struct conditional;
用法比较简单:
?
?
#include
#include
?
int main()?
{
? ?
首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇UVALive6814 Lexicography 下一篇UVA - 1616 Caravan Robbers 二分..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: