近日,分析了一小段参数范围检查的代码,有如进入伊甸园,感觉处处透露着精华。
奇妙之处在于:
1. 数据与业务分离;充分体现了高内聚、低耦合。
2. “模板嵌套”运用的炉火纯青,让人感受到抽象数据类型的强大。
3. 巧妙运用结构体、递归、枚举;让复杂的逻辑简易化。
4. 功能强大,可检查随机数、一定范围数据、特定步长数据(包含有符号与无符号数)。
希望自己在几年后也能写出这样高水平的代码。
#include <iostream.h> #include <stdio.h> #include <math.h> //typedef int int32_t //typedef unsigned int uint32_t typedef char char_t; //******************************************************************* //控制层 //******************************************************************* //数据类型结构体定义 struct Nil { //空结构体,用于边界数据 }; //for signed irregular range(for example: -100,-77,0, 1,3,5) //实际是一组集合 template< int32_t value, class U> struct SsetList { enum { RET = value }; typedef U Tail; }; //for unsigned irregular range(for example: 1,3,5,50,100) template< uint32_t value, class U> struct UsetList { enum { RET = value }; typedef U Tail; }; //for signed continuous regular range(for example: -3,-2,-1,0,1,2,3) template<int32_t startPos, int32_t stopPos, class U> struct SscopeList { enum { RET1 = startPos}; enum { RET2 = stopPos}; typedef U Tail; }; //for unsigned continuous regular range(for example: 0,1,2,3,4,5,6) template<uint32_t startPos, uint32_t stopPos, class U> struct UscopeList { enum { RET1 = startPos}; enum { RET2 = stopPos}; typedef U Tail; }; //for signed step-size regular range(use step-size 4 for example: -8,-4,0,4,8,12) template< int32_t startPos, int32_t stopPos, uint32_t stepSize, class U> struct SstepsizeList { enum { RET1 = startPos}; enum { RET2 = stopPos}; enum { RET3 = stepSize}; typedef U Tail; }; //for unsigned step-size regular range(use step-size 4 for example: 0,4,8,12,16,20,24) template< uint32_t startPos, uint32_t stopPos, uint32_t stepSize, class U> struct UstepsizeList { enum { RET1 = startPos}; enum { RET2 = stopPos}; enum { RET3 = stepSize}; typedef U Tail; }; //范围检查结构体 template< class AllowedList > struct Allowed; //allowed check Nil template<> struct Allowed<Nil> { static bool check( const int32_t value ) { (void)value; return false; } static bool check( const uint32_t value ) { (void)value; return false; } }; //检测随机值 template<int32_t head, class VTail > struct Allowed< SsetList<head, VTail> > { static bool check( const int32_t value ) { //如果检测值与第一个范围值相等,返回;否则递归检测下一个值 return (value == head) || Allowed< VTail >::check(value); } }; template<uint32_t head, class VTail > struct Allowed< UsetList<head, VTail> > { static bool check( const uint32_t value ) { return (value == head) || Allowed< VTail >::check(value); } }; //******************************************************************* template<class RangeList > struct Range; //range check Nil template<> struct Range<Nil> { static bool check( const int32_t value ) { (void)value; return false; } static bool check( const uint32_t value ) { (void)value; return false; } }; //检测一定范围内值 template<int32_t start, int32_t stop, class VTail > struct Range< SscopeList<start, stop, VTail> > { static bool check( const int32_t value ) { return (value >= start && value <= stop) || Range< VTail >::check(value); } }; template<uint32_t start, uint32_t stop, class VTail > struct Range< UscopeList<start, stop, VTail> > { static bool check( const uint32_t value ) { return (value >= start && value <= stop) || Range< VTail >::check(value); } }; /*小于特定值无符号值 template<uint32_t stop, class VTail > struct Range< UscopeList<0, stop, VTail> > { static bool check( const uint32_t value ) { return (value <= stop) || Range< VTail >::check(value); } }; */ //检测步长递变值 template<int32_t start, int32_t stop, uint32_t stepSize, class VTail > struct Range< SstepsizeList<start, stop, stepSize, VTail> > { static bool check( const int32_t value ) { return ((value >= start &&value <= stop &&abs(value - start) % stepSize == 0) || Range< VTail >::check(value)); } }; template<uint32_t start, uint32_t stop, uint32_t stepSize, class VTail > struct Range< UstepsizeList<start, stop, stepSize, VTail> > { static bool check( const uint32_t value ) { return (value >= start &&value <= stop &&(value - start) % stepSize == 0) || Range< VTail >::check(value); } }; /*小于特定值无符号值(有步长) template<uint32_t stop, uint32_t stepSize, class VTail > struct Range< UstepsizeList<0, stop, stepSize, VTail> > { static bool check( const uint32_t value ) { return (value <= stop &&value % stepSize == 0) || Range< VTail >::check(value); } }; */ //******************************************************************* class DataVerif { public: DataVerif():checkOk(true),pad1(0),pad2(0) { } virtual ~DataVerif() {} bool getStatus() const { return checkOk; } //protected: template <class RangeList, class AllowedList> void checkParam(int32_t value, const char_t* elemName) { if (checkOk) { if (!(Range<RangeList>::check(value) || Allowed<AllowedList>::check(value))) { checkOk = false; printf("[%d] Warning: Data element %s: value %d not within valid range.\n",__LINE__, elemName, value); } } } template <class RangeList, class AllowedList> void checkParam(uint32_t value, const char_t* elemName) { if (checkOk) { if (!(Range<RangeList>::check(value) || Allowed<AllowedList>::check(value))) { checkOk = false; printf("[%d]Warning: Data element %s: value %d not within valid range.\n",__LINE__, elemName, value); } } } bool checkOk; //Bool for keeping track of if checks of previous elements in struct were ok. uint8_t pad1; uint16_t pad2; }; //******************************************************************* //数据层 //******************************************************************* //random data typedef Nil SsetListRangeList; typedef SsetList<-8,SsetList<-4,SsetList<0,SsetList<4,SsetList<8,SsetList<9,SsetList<80,Nil > > > > > > > SsetListAllowedList; typedef Nil UsetListRangeList; typedef UsetList<8,UsetList<12,UsetList<16,UsetList<24,UsetList<32,UsetList<40,UsetList<80,Nil > > > > > > > UsetListAllowedList; //注意:对于随机数,数据存储在ListAllowedList中 // 对于规则数据,数据存储在ListRangeList中 // 实际可以将2者封装在一起,还没想明白分开做的好处 //for start-stop data typedef SscopeList<-8388608,8388352,Nil > SscopeListRangeList; typedef Nil SscopeListAllowedList; typedef UscopeList<0,100,Nil > UscopeListRangeList; typedef Nil UscopeListAllowedList; //for specific step-size data typedef SstepsizeList<-44,100,4, Nil> SstepsizeListRangeList; typedef Nil SstepsizeListAllowedList; typedef UstepsizeList<44,100,4, Nil> UstepsizeListRangeList; typedef Nil UstepsizeListAllowedList; DataVerif dV1; DataVerif dV2; DataVerif dV3; DataVerif dV4; DataVerif dV5; DataVerif dV6; #define checkSsetList(x) dV1.checkParam<SsetListRangeList,SsetListAllowedList >((x),#x) #define checkUsetList(x) dV2.checkParam<UsetListRangeList,UsetListAllowedList >((x),#x) #define checkSscopeList(x) dV3.checkParam<SscopeListRangeList,SscopeListAllowedList >((x),#x) #define checkUscopeList(x) dV4.checkParam<UscopeListRangeList,UscopeListAllowedList >((x),#x) #define checkSstepsizeList(x) dV5.checkParam<SstepsizeListRangeList,SstepsizeListAllowedList >((x),#x) #define checkUstepsizeList(x) dV6.checkParam<UstepsizeListRangeList,UstepsizeListAllowedList >((x),#x) //注意,为什么要把#x传进去,没想明白,好像也没什么实际意义。 //******************************************************************* //业务层 //******************************************************************* int main() { //********illegal******** printf("below is illegal value \n"); checkSsetList(1); checkUsetList(1); checkSscopeList(9999999); checkUscopeList(101); checkSstepsizeList(49); checkUstepsizeList(49); //********legal******* printf("below is legal value \n"); checkSsetList(-4); checkUsetList(12); checkSscopeList(9); checkUscopeList(9); checkSstepsizeList(8); checkUstepsizeList(48); return 1; }