- 浏览: 265610 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
daknife:
谢谢你的这篇文章,让我大概了解了select的一部分底层原理。 ...
Linux-2.6.25 select系统调用源码分析 -
gjlzjb:
非常有用,谢谢哈。另外问下,您是否用过Pheonix Syst ...
Why Map/Reduce? -
zhangyafei_kimi:
canbo 写道请问,我怎么生成安装包,提供给其它用户安装呢? ...
下载最新的Google Chrome源码并编译 -
canbo:
请问,我怎么生成安装包,提供给其它用户安装呢?
下载最新的Google Chrome源码并编译
本系列全部转载自kuibyshev.bokee.com
1. 模板元编程的原理
1.1. 函数式编程
1.1.1. 函数式编程的概念
从上面的例子可以看出,由于模板元编程借助的是C++模板的特化能力,使它的设计方法迥异于普通的C++编程习惯。比如我们不能够在元函数中使用变量,编译期显然只可能接受静态定义的常量,也就因此,我们不能够使用传统意义上的循环;要实现任何分支选择,唯一的方法是调用其它元函数或者使用递归。这种编程风格正是具有重要理论意义的函数式编程(Functional Programming)。
Kenneth C. Louden指出函数式编程有如下的特点:
所有的过程都是函数,并且严格地区分输入值(参数)和输出值(结果)。
没有变量或赋值(变量被参数替代)。
没有循环(循环杯递归调用替代)。
函数的值只取决于它的参数的值而与求得参数值的先后或者调用函数的路径无关。
函数是一类值。
上述的最后一点是一个很重要的性质。所谓“函数是一类值(First Class Value)”指的是函数和值是同等的概念,一个函数可以作为另外一个函数的参数,也可以作为值使用。如果函数可以作为一类值使用,那么我们就可以写出一些函数,使得这些函数接受其它函数作为参数并返回另外一个函数。比如定义了f和g两个函数,用compose(f,g)的风格就可以生成另外一个函数,使得这个函数执行f(g(x))的操作,则可称compose为高阶函数(Higher-order Function)。
1.1.2. 函数式编程在C++中的常用方法
如果排除上述的最后一点,那么C语言已经能完整模拟出函数式编程的风格,但是在C语言中,函数却并不能作为一类值。也许我们会想到函数指针,但是试想如果我们的函数需要返回另一个函数的指针:
typedef int(*IntProc) (int);
IntProc compose(IntProc f, IntProc g)
{
int tempProc(int x)
{
return f(g(x));
}
return tempProc;
}
这个例子是不能通过编译的,因为C语言禁止在函数中定义函数。
幸运的是,我们可以在C++中利用类和模板来解决这个问题,因为C++允许定义()操作符,建立所谓的仿函数(Functor)。所以对象既可以作为值来传递和调用,又可以像函数一样用obj(x)的语法来使用了;另一方面,利用模板对返回值的控制,就可以避免上面无法定义内部函数的矛盾了。例如在GCC的 STL中有一个不属于C++标准的compose1函数,可以接受两个定义了()操作符的对象作为函数参数,并返回一个能进行f(g(x))运算的对象:
template <class Operation1, class Operation2>
class unary_compose
: public unary_function<typename Operation2::argument_type,
typename Operation1::result_type> {
protected:
Operation1 op1;
Operation2 op2;
public:
unary_compose(const Operation1& x, const Operation2& y) :
op1(x), op2(y) {}
typename Operation1::result_type
operator()(const typename Operation2::argument_type& x) const {
return op1(op2(x));
}
};
template <class Operation1, class Operation2>
inline unary_compose<Operation1, Operation2>
compose1(const Operation1& op1, const Operation2& op2) {
return unary_compose<Operation1, Operation2>(op1, op2);
}
1.1.3. 模板元编程中的高阶函数
那么,使用C++的模板机制又是否可以满足元函数作为一类值使用呢?答案是肯定的,不过解答稍稍有点复杂,并不像上述compose1的解决方法一样优雅。
#include <iostream>
using namespace std;
template<int n>
struct f
{
static const int value=n+1;
};
template <int n>
struct g
{
static const int value=n+2;
};
template <template <int n> class op1, template <int n> class op2>
struct compose
{
template <int x>
struct return_type
{
static const int value=op1<op2<x>::value>::value;
};
};
int main()
{
typedef compose<f, g>::return_type<6> h;
cout<<h::value<<std::endl; //6+2+1=9
}
在这里,f和g是两个元函数,compose接受f和g作为参数,生成了一个可以计算f(g(x))的新函数,看起来能够得出正确的答案,但是却仍然有两个问题。
首先,在compose的模板参数中,不能直接使用类似于template <class op1, class op2>的写法,原因是C++的模板机制严格区分模板和类,我们无法把模板直接作为另一个模板的参数,唯一可行的方法是使用“作为类模板的模板参数(Class Template Template Parameter)”,这样就把f和g的参数类型限制死了。不过我们似乎仍然可以勉强接受这个限制,事实上模板机制对非类型的模板参数本来就存在着限制,现在的C++标准禁止浮点数、类对象和内部链接对象(比如字符串和全局指针)作为模板参数,所以非类型的模板参数实际上只剩下布尔型和整型可用,写成类似composeint和composebool 的两个类仍然有可行性(模板参数是无法重载的)。
其次,同样是C++的模板机制严格区分模板和类的缘故,返回值return_type是一个模板而并不是一个元函数(或者说是类)。
上述两点都隐含着一个最大共同问题,C++对“作为类模板的模板参数”作了很严格的限制,所以一旦定义了以后,其模板参数的个数不能改变。当然,在STL里面我们似乎习惯了这个限制并用重新定义函数的方式来避开这个限制。但在作为函数式编程的模板元编程里面,似乎应该要求以更优雅的方式来解决(事实上即使是常规编程下的高阶函数,也有函数库提供了更好的组合方式[5])。
现在我们仅仅用到了模板元编程的数值计算能力,还没有引入它对类型的处理能力,稍后在分析MPL时会重新讨论到这个问题,还会显示出高阶函数更大的使用障碍。幸而MPL提供了很好的解决方案,通过增加包装层和使用lambda演算的概念,高阶函数依然能用上,使得模板元编程能够符合函数式编程的要求。
Krzysztof Czarnecki曾利用模板元编程实现了一个很简单的LISP,而LISP就是典型的函数式编程语言。
总之既然C++模板能够使用函数式编程,那么也就意味着这个C++语言的子集已经是图灵完备的,因为任何计算都可以使用函数来描述,理论上模板元编程应该能完成图灵机上的一切运算。
当然,理论上的完备并不意味着实用性。尽管在C++中能够在某种程度上使用函数式编程的风格,但是从实用性和效率来说,大概没有程序员使用纯粹的函数编程方式。不过,在进行模板元编程的时候,由于语法的特殊性,却不得不使用纯粹函数式编程。因此,模板元编程与传统的C++命令式编程相差很大,并不符合大多数C++程序员的习惯,不但会带来编写上的困难,还增加了许多程序理解上的难度。那么,为什么要使用模板元编程呢?首先我们应当了解模板元编程能够做些什么,其次,模板元编程有可能用在什么地方。
发表评论
-
The Elements of Programing Style
2009-08-09 18:26 1270把代码写清楚,别耍小聪明。 想干什么,讲的简单点、直接点。 只 ... -
6个变态的C语言Hello World程序
2009-06-01 09:37 807转载自:http://cocre.com/?p=914 下面 ... -
在VS2005中使用IBM Purify的注意事项
2009-05-12 12:24 3999Rational Purify 使用及分析实例可以见这里htt ... -
boost.pool源码整理和使用说明
2007-07-22 13:49 270Source #ifndef __KIMI_BOOST_PO ... -
一个STL风格的动态二维数组
2007-07-22 18:05 1530#ifndef __KIMI_BOOST_ARRAY2#def ... -
boost.any源码整理和使用说明
2007-08-24 22:44 2093Source #include <algorithm& ... -
boost.array源码整理和使用说明
2007-08-24 22:45 1293Source #include <cstddef> ... -
boost.BOOST_STATIC_ASSERT源码整理和使用说明
2007-08-24 22:49 1364Source #include <boost/conf ... -
boost.shared_ptr源码整理和使用说明
2007-08-24 22:51 4189Source #pragma once //share ... -
boost.lexical_cast源码整理和使用说明
2007-08-24 22:55 1544Source #include <cstddef> ... -
编译期判断类的继承性
2007-08-24 23:00 1109介绍一个雕虫小技:编译期判断类的继承性。具体来说就是类型U是否 ... -
boost.type_traits源码整理和使用说明(1)
2007-08-28 01:35 2079Introduction The Boost type-tr ... -
泛型快速排序
2007-08-28 03:20 945Source #ifndef kimi_quicksort ... -
C++ Meta Programming 和 Boost MPL(1)
2007-08-30 23:01 1605本系列全部转载自kuibyshev.bokee.com ... -
C++ Meta Programming 和 Boost MPL(3)
2007-08-30 23:06 1528本系列全部转载自kuibyshev.bokee.com ... -
C++ Meta Programming 和 Boost MPL(4)
2007-08-30 23:07 1707本系列全部转载自kuibyshev.bokee.com ... -
泛型归并排序
2007-09-18 00:23 1213#define SENTINEL_CARD (-1) # ... -
泛型插入排序
2007-09-18 00:25 1210#pragma once #include <iter ... -
boost.tuple源码整理和使用说明
2007-10-07 23:13 1601Introduction A tuple (or n-tup ... -
才发现VC中也可以检测内存泄漏
2009-03-30 14:54 1381#include <stdio.h> ...
相关推荐
Boost库中的MPL(Meta-Programming Library)是一个专门为模板元编程设计的库,它包含了许多创新性的概念,如类型序列、算法和表达式模板,极大地扩展了C++模板的功能。 C++元编程的核心是模板,模板不仅用于生成...
在泛型编程方面,书中会讲解BOOST.MPL(Meta Programming Library),这是一个强大的元编程库,允许在编译时进行计算和类型操作,这对于创建高效且高度定制化的模板类和函数至关重要。另外,BOOST.Fusion提供了用于...
Boost.MPL(Meta-Programming Library)和Boost.TypeTraits库提供了编译时元编程工具,允许开发者在编译期间进行类型检查和计算。 Boost库的设计理念是提高C++的可移植性、效率和可维护性。通过使用Boost库,...
6. **模式匹配和元编程**:例如 MPL(Meta-Programming Library)允许在编译时进行计算。 7. **序列化**:提供将数据结构序列化到文件或内存流的能力,便于持久化存储。 8. **正则表达式**:实现了标准C++库尚未...
3. **模板元编程**:Boost.MPL(Meta-Programming Library)允许在编译时进行计算,提高了代码的效率和灵活性,是C++模板元编程的重要工具。 4. **正则表达式**:Boost.Regex库提供了符合POSIX标准的正则表达式操作...
本项目旨在利用C++0x的可变模板参数来实现一个类似于Boost MPL(Meta Programming Library)的类型容器。Boost MPL是一个元编程库,它提供了一种在编译时处理类型和数值的方法,是C++模板元编程的重要工具。 首先,...
2. **模板元编程**:Boost.MPL(Meta-Programming Library)是一个强大的模板元编程库,允许在编译时执行计算,极大地提高了代码的效率。 3. **智能指针**:Boost库中的智能指针,如Boost.SmartPtr,可以有效地管理...
1. **模板元编程**:Boost.MPL(Meta-Programming Library)允许开发者在编译时执行计算,创建类型列表,实现强大的类型系统操作。 2. **智能指针**:Boost.Smart_ptr包括shared_ptr、unique_ptr和weak_ptr,提供了...
模板元编程是Boost库的另一大亮点,如Boost.MPL(Meta-Programming Library)提供了丰富的元函数和元操作,使得程序员可以在编译时进行计算。这对于构建高效、类型安全的代码至关重要。 在并发处理方面,Boost库...
3. **模板元编程**:Boost.MPL(Meta-Programming Library)提供了一种在编译时进行计算和操作的方式,增强了C++模板的功能,使开发者能够在编译期进行更复杂的类型操作。 4. **并发与多线程**:Boost.Thread库提供...
例如,`Boost.MPL`(Meta-Programming Library)提供了丰富的元函数和容器,实现编译时的泛型编程。 3. **智能指针**:Boost库提供了多种智能指针,如`shared_ptr`、`unique_ptr`和`weak_ptr`,它们在内存管理上比...
- **Boost.MPL**(Meta Programming Library):支持元编程,即在编译时进行计算。 - **Boost.Fusion**:用于组合和操作不同类型的数据结构。 - **Boost.TypeTraits**:提供了对类型信息的操作能力。 - **Boost....
例如,Boost.TypeTraits库提供了许多工具来查询类型属性,而Boost MPL(Meta Programming Library)则提供了一套完整的元编程框架。 3. **智能指针**:Boost库中的smart_ptr(包括shared_ptr、unique_ptr、weak_ptr...
- **泛型编程**: Boost MPL(Meta-Programming Library)和Boost.Fusion提供元编程和类型序列处理工具,是模板元编程的强大工具。 4. **智能指针的应用场景** - **内存管理**: 智能指针可以自动管理内存,防止...
Boost库中包含了许多用于模板元编程的工具,如`mpl`(Meta-programming Library)和`fusion`,它们可以帮助开发者创建更高效、更类型安全的代码。 2. **标准模板库(Standard Template Library, STL)** STL是C++...
10. **元编程**(Meta-Programming):Boost.MPL(Metaprogramming Library)和Boost.TypeTraits是元编程的重要工具,它们允许在编译时执行计算和检查类型属性。 11. **模板元编程**(Template Meta-Programming)...
Boost.MPL(Meta-Programming Library)是一个强大的模板元编程库,允许程序员在编译时执行计算和创建类型。 此外,Boost还包含了对智能指针(如BoostSharedPtr和BoostUniquePtr)、函数对象绑定(Boost.Bind和...
4. **Boost库中的元编程工具**:Boost库提供了丰富的元编程工具,如Type Traits、 MPL(Meta Programming Library)、Preprocessor等,这些工具可以帮助开发者编写出更加高效和强大的代码。 5. **编译时算术和逻辑...
1. **模板元编程**:BOOST库中的Boost.MPL(Meta-Programming Library)提供了一种在编译时进行计算的方法,这对于创建高度定制化和高效的代码非常有用。 2. **智能指针**:如Boost.PtrContainer和Boost.SmartPtr,...
标签中的“boost”,“c++_meta”和“programming”揭示了文档的焦点是关于Boost库、C++中的元编程技术以及通用编程的实践。 从提供的内容片段中,我们可以看到,文档提到了Boost C++元编程库的作者Aleksey ...