作者:yorksen 来源:qzone   酷勤网收集 2007-09-20

摘要
  以下程序在GCC 3.4.2下编译通过,并且在GCC 3.0以后的所有版本中都能成功编译(GCC是一个开源、免费的编译平台),但以下源代码在Visual C++的现有版本或今后即将出现的任何一个版本中都不可能正常通过...

公司里一直用的是老旧过时的VC6做C++开发,而微软的C++IDE总是对C++支持得不好。我平时遇到问题时会去查阅C++98/03标准,因此知道C++语言中部分元素设计背后的智慧。但是,每当我将标准中的建议放在VC中尝试时,却经常发现VC内置的C++编译器在实现上的一些可笑之处!嗯,可能有人会觉得我有些过急了,但VC的CL编译器确实存在很多很多BUG,这些BUG不是程序本身的问题,而是微软的开发人员不去认真研究和思考标准中的各种建议而浮躁的去做他们的产品,赶他们的进度造成的,对此我会抽控专门写一篇文章来揭露这些问题(这些问题不仅存在于C++98标准制定期间草率发布的Visual C++ 6.0上,而且在VC2005中也有,并且我敢保证在即将发布的VC2008上也有类似问题),而现在,我只想让自己放纵一下,就以《Modern C++ Design》中传授的泛型绝招遍一个求解素数问题的纯泛型算法来发泄心中的不满吧!

所谓“素数”就是只能被1或自己整数的数,以下程序提供了如下接口来完成素数的求解:
IsPrimeNumber(n) 用于判断制定整数n是否素数,若是则返回1(true),否则返回0(false)
PrintAllPrimeNum(start,end) 用于打印[start,end]描述的闭区间中的所有素数。

泛型算法的好处我原来也说过了,那就是所有结果都是在程序编译时由编译器计算出来,而在程序运行时不会再花费额外开销去计算,但由于这样会导致编译后的可执行文件大小的膨胀严重,并且将程序写成这样也会降低源代码的编译速度,因此这种编程泛式在实际开发中并不常用,即使要用,也用在解决接口兼容的问题上。

以下程序在GCC 3.4.2下编译通过,并且在GCC 3.0以后的所有版本中都能成功编译(GCC是一个开源、免费的编译平台),但以下源代码在Visual C++的现有版本或今后即将出现的任何一个版本中都不可能正常通过(Visual C++是微软专有的,并且费用昂贵的开发C++环境),除非某天微软雇用的这些书呆子们真正领悟到了C++背后的精髓,否则这种情况将不会得到任何改善!~:

#include <cstdlib>
#include <iostream>
using namespace std;
//--------------------------
// 判断素数的泛型算法
// 作者:编程赎罪 yorksen 2007/8/23
//
// 提供接口:
// IsPrimeNumber(n) 判断n是否是素数,是返回"true"
// PrintAllPrimeNum(start,end) 打印[start,end]闭区间内的所有素数
//-------------------------
// 定义构造整数链表的节点
template<unsigned long long n,class T>
struct ValueNode
{
enum{value = n};
typedef T NextNode;
};
struct EmptyNode
{
typedef EmptyNode NextNode;
};
// 用于判断两个整数中哪个整数大
template<unsigned long long num1, unsigned long long num2,bool rst>
struct MaxMinSelector
{
enum{max = num1};
enum{min = num2};
};
template<unsigned long long num1, unsigned long long num2>
struct MaxMinSelector<num1,num2,false>
{
enum{max = num2};
enum{min = num1};
};
template<unsigned long long num1, unsigned long long num2>
struct MaxMinTrait
{
enum{max = MaxMinSelector<num1,num2,(num1 > num2)>::max};
enum{min = MaxMinSelector<num1,num2,(num1 > num2)>::min};
};
// 用于生成值范围为start 到 end 的整数链表
template<unsigned long long start,unsigned long long end>
struct MakeList
{
private:
enum{front = MaxMinTrait<start,end>::min};
enum{Tail = MaxMinTrait<start,end>::max};

public:
typedef ValueNode<front,typename MakeList<front+1,Tail>::result> result;
};
template<unsigned long long end>
struct MakeList<end,end>
{
typedef ValueNode<end,EmptyNode> result;
};
// 用于打印链表中的所有节点上的整数值
template<class ValueList>
void print_each()
{
cout<<ValueList::value<<" "<<endl;
print_each<typename ValueList::NextNode>();
}
template<>
void print_each<EmptyNode>()
{
cout<<endl;
}
// PrimeSelector和IsPrimeNumImpl用于判断IsPrimeNumImple的n参数
// 指定的整数是否"不能"被ValueList中除了1和n之外的每个数整除
template<unsigned long long n,bool rst,class ValueList>
struct PrimeSelector
{
enum{result = false};
};
template<unsigned long long n,class ValueList>
struct IsPrimeNumImpl
{
enum{result = PrimeSelector<n,static_cast<bool>(n % ValueList::value),ValueList>::result};
};
template<unsigned long long n,class RestList>
struct IsPrimeNumImpl<n,ValueNode<n,RestList> >
{
enum{result = IsPrimeNumImpl<n,RestList>::result};
};
template<unsigned long long n,class RestList>
struct IsPrimeNumImpl<n,ValueNode<1,RestList> >
{
enum{result = IsPrimeNumImpl<n,RestList>::result};
};
template<unsigned long long n>
struct IsPrimeNumImpl<n,EmptyNode>
{
enum{result = true};
};
template<unsigned long long n,class ValueList>
struct PrimeSelector<n,true,ValueList>
{
enum{result = IsPrimeNumImpl<n,typename ValueList::NextNode>::result};
};
// 该函数通过上面实现的IsPrimeNumImpl判断指定整数n是否是一个素数
template<unsigned long long n>
struct IsPrimeNum
{
typedef typename MakeList<2,n>::result value_list;
enum{result = IsPrimeNumImpl<n,value_list>::result};
};
// 特化,1是素数直接返回"真"
template<>
struct IsPrimeNum<1>
{
enum{result = true};
};
/***************************************************/
// 提供给应用方使用的用于判断指定n是否是素数的宏封装
// 参数: n 为指定待判断 的整数
// 返回: 若n为素数则返回 "1 true"
// 否则返回 "0 false"
// 说明:无
/***************************************************/
#define IsPrimeNumber(n) IsPrimeNum<n>::result
template<class ListNode,bool rst>
struct FindPrimeSelector
{
typedef ListNode result;
};
template<class ValueList>
struct FindFirstPrimeNum
{
typedef typename FindPrimeSelector<ValueList,IsPrimeNum<ValueList::value>::result>::result result;
};
template<>
struct FindFirstPrimeNum<EmptyNode>
{
typedef EmptyNode result;
};
template<class ListNode>
struct FindPrimeSelector<ListNode,false>
{
typedef typename FindFirstPrimeNum<typename ListNode::NextNode>::result result;
};
template<class FirstPrimeNode>
struct MakePrimeNumListImpl
{
typedef typename FindFirstPrimeNum<typename FirstPrimeNode::NextNode>::result RestList;
typedef ValueNode<FirstPrimeNode::value,typename MakePrimeNumListImpl<RestList>::result > result;
};
template<>
struct MakePrimeNumListImpl<EmptyNode>
{
typedef EmptyNode result;
};
template<unsigned long long start, unsigned long long end>
struct MakePrimeNumList
{
private:
typedef typename MakeList<start,end>::result ValueList;
public:
typedef typename MakePrimeNumListImpl<typename FindFirstPrimeNum<ValueList>::result>::result result;
};
/***************************************************/
// 提供给应用方使用的用于打印指定范围内的所有素数
// 参数: start 为起始数
// end 为结束数
// 返回: 无
// 说明: 将打印[start,end]闭区间内的所有素数,其中
// start参数的值可以大于或等于end参数的值
/***************************************************/
#define PrintAllPrimeNum(start,end) print_each<MakePrimeNumList<start,end>::result>()

int main(int argc, char *argv[])
{
// 判断14是否是素数
cout<<IsPrimeNumber(14)<<endl;

// 打印1到10之内的所有素数
PrintAllPrimeNum(1,10);

system("PAUSE");
return EXIT_SUCCESS;
}

运行结果:


最后需要说明的是,我不是高手,我只是一个不断学习,不断去领悟隐藏在现象背后的本质的初学者。世上本来就不存在什么高手;当一个人自诩自己是高手的时候,那就表明了他的境界已经提升到了尽头,他将像一个已经装满的水壶,再也放不下任何别的什么东西。

来自:http://50723610.qzone.qq.com/blog/5

分类: 算法艺术 设计模式



关于酷勤 | 联系方式 | 免责声明 | 友情链接