15) .实现可变参数的(成员/非成员)模板函数的回调,消除类似代码

完整的源代码及用法测试代码可以在我的资源中去下载.

C++语法不支持模板函数/模板成员函数作为回调函数,同时把运行期代码向编译期代码转换也只有switch...case或者if..else能够实现。

如果case比较多的时候,代码非常臃肿,而且类似的大片代码中,往往只有一个参数的不同,其它都是相同的。这对于用户来说,都是一个大量的重复性的hard-code性的负担,而且也容易导致出错。

本库采用了封装,可以把运行性的switch...case/if..else分支选择转换为编译期的代码,支持模板函数的回调,并且支持最多6个可变参数(可以简易扩充参数个数),从而可以大幅度地减少代码量,(代码量可以减少到原代码的1/N,N为case数目)。并且由于是编译期代码,从而保证不会出错(出错将导致编译失败)。

并且附带提供了CEnumRange,可以检测一个枚举值是否在枚举范围内。

#ifndef __test_traverseEnum_h_

#define __test_traverseEnum_h_

/***********************************************************************************************************************

* Description         : test file for <utility\traverseEnum.h>

* Author              : Shen.Xiaolong (Shen Tony,2009-2014)

* Mail                : [email protected],  [email protected]

* verified platform   : VS2008 (2014/11/02 11:42:08.21)

* copyright:          : free to use / modify / sale in free and commercial software.

*                       Unique limit: MUST keep those copyright comments in all copies and in supporting documentation.

* usage demo          : #define RUN_EXAMPLE_TRAVERSEENUM to run this demo

***********************************************************************************************************************/

#include "testconfig.h"

#include <utility/traverseEnum.h>

#include "test_macroDef.h"

#include "utility/macroDef.h"

#include "utility/parameterWrp.h"

//#define RUN_EXAMPLE_TRAVERSEENUM

#ifdef COMPILE_EXAMPLE_ALL

#define COMPILE_EXAMPLE_TRAVERSEENUM

#endif

#ifdef RUN_EXAMPLE_ALL

#define RUN_EXAMPLE_TRAVERSEENUM

#endif

#if defined(RUN_EXAMPLE_TRAVERSEENUM) && !defined(COMPILE_EXAMPLE_TRAVERSEENUM)

#define COMPILE_EXAMPLE_TRAVERSEENUM

#endif

////////////////////////////////////////////usage demo code//////////////////////////////////////////////////////////////////

#ifdef COMPILE_EXAMPLE_TRAVERSEENUM

//sequential enum value, it can apply SKIP_ENUM_NEXT except you want to skip some enum value(s)

enum SeqEunm {S_Val_Min,S_Val_1,S_Val_2,S_Val_3,S_Val_4,S_Val_5,S_Val_6,S_Val_7,S_Val_Max};

typedef UtilExt::CEnumRange<SeqEunm,S_Val_Min,S_Val_Max>        SeqEnumRange;

SKIP_ENUM_ONE(SeqEnumRange,S_Val_4);                            //skip 4

//test SKIP_ENUM_ONE

typedef UtilExt::CEnumRange<SeqEunm,S_Val_1,S_Val_6>            SeqEnumSkipOneRange;

// SKIP_ENUM_ONE(SeqEnumSkipOneRange,S_Val_1);                  //fail because S_Val_1 is head of SeqEnumSkipOneRange

// SKIP_ENUM_ONE(SeqEnumSkipOneRange,S_Val_6);                  //fail because S_Val_6 is tail of SeqEnumSkipOneRange

SKIP_ENUM_ONE(SeqEnumSkipOneRange,S_Val_3);                     //OK,   S_Val_3 is not head or tail

//non-sequential enum type : value 2,4 is lack

enum NonSeqEunm

{

NS_Val_Min = 0 ,

NS_Val_1   = 1,

NS_Val_3   = 3,

NS_Val_5   = 5,

NS_Val_8   = 8,

NS_Val_Max

};

typedef UtilExt::CEnumRange<NonSeqEunm,NS_Val_Min,NS_Val_Max>   NonSeqEnumRange;

//skip NS_Val_3 when traverse enum type "DemoEunm" : jump from NS_Val_2 to NS_Val_4

SKIP_ENUM_MIDDLE(NonSeqEnumRange,NS_Val_1,NS_Val_3);                      //skip 2

SKIP_ENUM_MIDDLE(NonSeqEnumRange,NS_Val_3,NS_Val_5);                      //skip 4

SKIP_ENUM_MIDDLE(NonSeqEnumRange,NS_Val_5,NS_Val_8);                      //skip 6 ,7

//SKIP_ENUM_NEXT(EnumRange,NS_Val_3,NS_Val_1);                    //Fail because  NS_Val_3 > NS_Val_1

//SKIP_ENUM_NEXT(EnumRange,NS_Val_3,DemoEunm(NS_Val_Max+1));      //Fail because  DemoEunm(NS_Val_Max+1) is not in range

namespace DemoUsage

{

template<SeqEunm TVal>

bool globalEnumFunc(int a,char* pStr)

{

printf("globalEnumFunc [%d],param=%d,%s",TVal+1,a,pStr?pStr:"NULL");

return true;

}

Declare_Template_Global_CallBack(::DemoUsage::,SeqEunm,globalEnumFunc);

struct CNonSeqEunmInterface_1

{

CNonSeqEunmInterface_1(int p) : m_bResult(false),m_param(p){};

template<NonSeqEunm TVal>

void apply()

{

dbgOutput(TXT("\n\n[NonSeqEunm]Enum value is %d."),TVal);

dbgOutput(TXT("\n[CEnumInterface_1::apply] %d"),TVal);

m_bResult = (TVal+m_param) > NS_Val_Max;

}

bool m_bResult;

int m_param;

};

Declare_Template_Mem_CallBack(::DemoUsage::,CNonSeqEunmInterface_1,NonSeqEunm,apply );

struct CNonSeqEunmInterface_2

{

CNonSeqEunmInterface_2(VCHAR* pStr) : m_bResult(false),m_pStr(pStr){};

template<NonSeqEunm TVal>

void apply()

{

dbgOutput(TXT("\n\n[NonSeqEunm]Enum value is %d."),TVal);

dbgOutput(TXT("\n[CEnumInterface_2::apply] %s %d"),m_pStr,TVal);

m_bResult = (TVal+2) > NS_Val_Max;

}

bool m_bResult;

VCHAR* m_pStr;

};

Declare_Template_Mem_CallBack(::DemoUsage::,CNonSeqEunmInterface_2,NonSeqEunm,apply );

struct CSeqEunmInterface_1

{

CSeqEunmInterface_1(int p) : m_bResult(false),m_param(p){};

template<SeqEunm TVal>

void apply()

{

dbgOutput(TXT("\n\n[SeqEunm]Enum value is %d."),TVal);

dbgOutput(TXT("\n[CSeqEunmInterface_1::apply] %d"),TVal);

m_bResult = (TVal+m_param) > NS_Val_Max;

}

bool m_bResult;

int m_param;

};

Declare_Template_Mem_CallBack(::DemoUsage::,CSeqEunmInterface_1,SeqEunm,apply );

struct CSeqEunmInterface_2

{

CSeqEunmInterface_2(VCHAR* pStr) : m_bResult(false),m_pStr(pStr){};

template<SeqEunm TVal>

void apply()

{

dbgOutput(TXT("\n\n[SeqEunm]Enum value is %d."),TVal);

dbgOutput(TXT("\n[CSeqEunmInterface_2::apply] %s %d"),m_pStr,TVal);

m_bResult = (TVal+2) > NS_Val_Max;

}

bool m_bResult;

VCHAR* m_pStr;

};

Declare_Template_Mem_CallBack(::DemoUsage::,CSeqEunmInterface_2,SeqEunm,apply );

Declare_Template_Mem_CallBack(::DemoUsage::,CTestEnumSuite,SeqEunm,printEnum );

Declare_Template_Mem_CallBack(::DemoUsage::,CTestEnumSuite,SeqEunm,printNext );

Declare_Template_Mem_CallBack(::DemoUsage::,CTestEnumSuite,SeqEunm,print2Param );

Declare_Template_Mem_CallBack(::DemoUsage::,CTestEnumSuite,SeqEunm,inOutParam );

class CTestEnumSuite

{

public:

template<SeqEunm TVal>

bool printEnum()

{

outputTxt((TXT("CTestEnumSuite::printEnum [%d]"),TVal));

return true;

}

template<SeqEunm TVal>

bool printNext()

{

outputTxt((TXT("CTestEnumSuite::printNext [%d]"),TVal+1));

return true;

}

template<SeqEunm TVal>

void inOutParam(char p1,int& outParam)

{

outputTxt((TXT("CTestEnumSuite::inOutParam [%d]"),TVal+1));

outParam = 4;

}

template<SeqEunm TVal>

bool print2Param(int a,char* pStr)

{

printf("CTestEnumSuite::print2Param [%d],param=%d,%s",TVal+1,a,pStr?pStr:"NULL");

return true;

}

void testEntry()

{

int a = 5;

char* pStr = "in testEntry";

SeqEunm tVal = SeqEunm(rand()%S_Val_Max);

//test member function

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(tVal,CTestEnumSuite_SeqEunm_printEnum<CTestEnumSuite>(),makeParamPackage(*this))));

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(tVal,CTestEnumSuite_SeqEunm_printNext<CTestEnumSuite>(),makeParamPackage(*this))));

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(tVal,CTestEnumSuite_SeqEunm_print2Param<CTestEnumSuite>(),makeParamPackage(*this,a,pStr))));

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(tVal,Template_Mem_Callback_Obj(CTestEnumSuite,SeqEunm,printEnum),makeParamPackage(*this))));

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(tVal,Template_Mem_Callback_Obj(CTestEnumSuite,SeqEunm,printNext),makeParamPackage(*this))));

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(tVal,Template_Mem_Callback_Obj(CTestEnumSuite,SeqEunm,print2Param),makeParamPackage(*this,a,pStr))));

//test in-out parameter

char p1 = 3;

int outP = 6;

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(tVal,Template_Mem_Callback_Obj(CTestEnumSuite,SeqEunm,inOutParam ),makeParamPackage(*this,p1,outP))));

ASSERT_AND_LOG(6==outP);

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(tVal,Template_Mem_Callback_Obj(CTestEnumSuite,SeqEunm,inOutParam ),makeParamPackage(*this,p1,MIOP(outP)))));

ASSERT_AND_LOG(4==outP);

//test global function

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(tVal,_SeqEunm_globalEnumFunc(),makeParamPackage(a,pStr))));

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(tVal,Template_Global_Callback_Obj(SeqEunm,globalEnumFunc),makeParamPackage(a,pStr))));

}

};

template<SeqEunm TVal >

struct TValMap;

template<>

struct TValMap<S_Val_6> : public Value2Type<bool (DemoUsage::CTestEnumSuite::*)(void) ,&CTestEnumSuite::printEnum<S_Val_6> > {};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

inline void showUsage_traverseEnum()

{

PrintUsage();

using namespace UtilExt;

typedef SeqEnumRange::Min_T                                 SEnumValueMin;

typedef SeqEnumRange::Max_T                                 SEnumValueMax;

typedef NonSeqEnumRange::Min_T                              NSEnumValueMin;

typedef NonSeqEnumRange::Max_T                              NSEnumValueMax;

//test UtilExt.CEnumRange.Min_T/Max_T

Static_Assert((CGetEnumValue<typename NonSeqEnumRange::Min_T>::value==NS_Val_Min));

Static_Assert((CGetEnumValue<typename NonSeqEnumRange::Max_T>::value==NS_Val_Max));

Static_Assert((CGetEnumValue<typename SeqEnumRange::Min_T>::value==S_Val_Min));

Static_Assert((CGetEnumValue<typename SeqEnumRange::Max_T>::value==S_Val_Max));

//test UtilExt.CEnumValue.Next

Static_Assert((CGetEnumValue<typename CEnumValue<SeqEnumRange,S_Val_1>::Next<true>::type>::value==S_Val_2));

Static_Assert((CGetEnumValue<typename CEnumValue<SeqEnumRange,S_Val_1>::Next<false>::type>::value==S_Val_Min));

Static_Assert(!(CGetEnumValue<typename CEnumValue<SeqEnumRange,S_Val_1>::Next<false>::type>::value==S_Val_2));

Static_Assert((CGetEnumValue<typename CEnumValue<NonSeqEnumRange,NS_Val_1>::Next<true>::type>::value==NS_Val_3));

Static_Assert((CGetEnumValue<typename CEnumValue<NonSeqEnumRange,NS_Val_1>::Next<false>::type>::value==NS_Val_Min));

Static_Assert(!(CGetEnumValue<typename CEnumValue<NonSeqEnumRange,NS_Val_1>::Next<false>::type>::value==NS_Val_3));

//test UtilExt.CEnumValue.Last

Static_Assert((CGetEnumValue<typename CEnumValue<SeqEnumRange,S_Val_3>::Last<true>::type>::value==S_Val_2));

Static_Assert((CGetEnumValue<typename CEnumValue<SeqEnumRange,S_Val_3>::Last<false>::type>::value==S_Val_5));       //because SKIP_ENUM_ONE(SeqEnumRange,S_Val_4);

Static_Assert(!(CGetEnumValue<typename CEnumValue<SeqEnumRange,S_Val_3>::Last<false>::type>::value==S_Val_2));

Static_Assert((CGetEnumValue<typename CEnumValue<NonSeqEnumRange,NS_Val_3>::Last<true>::type>::value==NS_Val_1));

Static_Assert((CGetEnumValue<typename CEnumValue<NonSeqEnumRange,NS_Val_3>::Last<false>::type>::value==NS_Val_5));

Static_Assert(!(CGetEnumValue<typename CEnumValue<NonSeqEnumRange,NS_Val_3>::Last<false>::type>::value==NS_Val_1));

//test UtilExt.CGetEnumRange

Static_Assert((IsSameType<typename CGetEnumRange<SEnumValueMin>::type,SeqEnumRange>::value));

Static_Assert((IsSameType<typename CGetEnumRange<SEnumValueMax>::type,SeqEnumRange>::value));

Static_Assert((IsSameType<typename CGetEnumRange<CEnumValue<SeqEnumRange,S_Val_3> >::type,SeqEnumRange>::value));

Static_Assert((IsSameType<typename CGetEnumRange<CEnumValue<SeqEnumRange,S_Val_6> >::type,SeqEnumRange>::value));

Static_Assert((IsSameType<typename CGetEnumRange<CEnumValue<SeqEnumRange,S_Val_2> >::type,typename CGetEnumRange<CEnumValue<SeqEnumRange,S_Val_1> >::type>::value));

Static_Assert((IsSameType<typename CGetEnumRange<SEnumValueMax>::type,typename CGetEnumRange<SEnumValueMin>::type>::value));

Static_Assert((IsSameType<typename CGetEnumRange<NSEnumValueMin>::type,NonSeqEnumRange>::value));

Static_Assert((IsSameType<typename CGetEnumRange<NSEnumValueMax>::type,NonSeqEnumRange>::value));

Static_Assert((IsSameType<typename CGetEnumRange<CEnumValue<NonSeqEnumRange,NS_Val_3> >::type,NonSeqEnumRange>::value));

Static_Assert((IsSameType<typename CGetEnumRange<CEnumValue<NonSeqEnumRange,NS_Val_5> >::type,NonSeqEnumRange>::value));

Static_Assert((IsSameType<typename CGetEnumRange<CEnumValue<NonSeqEnumRange,NS_Val_Min> >::type,typename CGetEnumRange<CEnumValue<NonSeqEnumRange,NS_Val_1> >::type>::value));

Static_Assert((IsSameType<typename CGetEnumRange<NSEnumValueMax>::type,typename CGetEnumRange<NSEnumValueMin>::type>::value));

//test UtilExt.CGetEnumRangeMax/CGetEnumRangeMin

Static_Assert((CGetEnumRangeMax<CEnumValue<NonSeqEnumRange,NS_Val_3> >::value==NS_Val_Max));

Static_Assert((CGetEnumRangeMax<CEnumValue<NonSeqEnumRange,NS_Val_5> >::value==NS_Val_Max));

Static_Assert((CGetEnumRangeMax<CEnumValue<SeqEnumRange,S_Val_3> >::value==S_Val_Max));

Static_Assert((CGetEnumRangeMax<CEnumValue<SeqEnumRange,S_Val_5> >::value==S_Val_Max));

Static_Assert((CGetEnumRangeMin<CEnumValue<NonSeqEnumRange,NS_Val_3> >::value==NS_Val_Min));

Static_Assert((CGetEnumRangeMin<CEnumValue<NonSeqEnumRange,NS_Val_5> >::value==NS_Val_Min));

Static_Assert((CGetEnumRangeMin<CEnumValue<SeqEnumRange,S_Val_3> >::value==S_Val_Min));

Static_Assert((CGetEnumRangeMin<CEnumValue<SeqEnumRange,S_Val_5> >::value==S_Val_Min));

//test UtilExt.CGetEnumValue

Static_Assert((CGetEnumValue<typename CEnumValue<NonSeqEnumRange,NS_Val_3>::Next<true>::type>::value==NS_Val_5));

Static_Assert((CGetEnumValue<typename CEnumValue<SeqEnumRange,S_Val_3>::Next<true>::type>::value==S_Val_5));  //because SKIP_ENUM_ONE(SeqEnumRange,S_Val_4);

//test UtilExt.CGetEnumType

Static_Assert((IsSameType<typename CGetEnumType<SEnumValueMin>::type,typename CGetEnumType<SEnumValueMax>::type>::value));

Static_Assert((IsSameType<typename CGetEnumType<NSEnumValueMin>::type,typename CGetEnumType<NSEnumValueMax>::type>::value));

Static_Assert((IsSameType<typename CGetEnumType<NonSeqEnumRange>::type,typename CGetEnumType<NSEnumValueMax>::type>::value));

Static_Assert((IsSameType<typename CGetEnumType<NonSeqEnumRange>::type,typename CGetEnumType<NSEnumValueMin>::type>::value));

Static_Assert(!(IsSameType<typename CGetEnumType<NSEnumValueMin>::type,typename CGetEnumType<SEnumValueMin>::type>::value));

//test UtilExt.CEnumInRange

Static_Assert(!(CEnumInRange<typename NSEnumValueMin::Last<true>::type>::value));

Static_Assert((CEnumInRange<typename NSEnumValueMax::Last<true>::type>::value));

Static_Assert((CEnumInRange<typename NSEnumValueMin::Next<true>::type>::value));

Static_Assert(!(CEnumInRange<typename NSEnumValueMax::Next<true>::type>::value));

Static_Assert((CEnumInRange<typename NSEnumValueMin::Last<false>::type>::value));

Static_Assert(!(CEnumInRange<typename NSEnumValueMax::Last<false>::type>::value));

Static_Assert(!(CEnumInRange<typename NSEnumValueMin::Next<false>::type>::value));

Static_Assert((CEnumInRange<typename NSEnumValueMax::Next<false>::type>::value));

CNonSeqEunmInterface_1 nsCallObj_1(rand()%NS_Val_Max);

CNonSeqEunmInterface_2 nsCallObj_2(TXT("I am CEnumInterface_2 :"));

CSeqEunmInterface_1 sCallObj_1(rand()%S_Val_Max);

CSeqEunmInterface_2 sCallObj_2(TXT("I am CSeqEunmInterface_2 :"));

CTestEnumSuite testObj;

testObj.testEntry();

//test UtilExt.CTraverseEnum.apply

ASSERT_AND_LOG((CTraverseEnum<NonSeqEnumRange,true>::apply(NS_Val_5,Template_Mem_Callback_Obj(CNonSeqEunmInterface_1,NonSeqEunm,apply),makeParamPackage(nsCallObj_1))));                    //test OK case

ASSERT_AND_LOG((CTraverseEnum<NonSeqEnumRange,false>::apply(NS_Val_5,Template_Mem_Callback_Obj(CNonSeqEunmInterface_1,NonSeqEunm,apply),makeParamPackage(nsCallObj_1))));                   //test OK case

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(S_Val_5,Template_Mem_Callback_Obj(CSeqEunmInterface_1,SeqEunm,apply),makeParamPackage(sCallObj_1))));                               //test OK case

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,false>::apply(S_Val_5,Template_Mem_Callback_Obj(CSeqEunmInterface_1,SeqEunm,apply),makeParamPackage(sCallObj_1))));                              //test OK case

//test UtilExt.CTraverseEnum.applyFrom

ASSERT_AND_LOG((CTraverseEnum<NonSeqEnumRange,true>::applyFrom<NS_Val_1>(NS_Val_3,Template_Mem_Callback_Obj(CNonSeqEunmInterface_2,NonSeqEunm,apply),makeParamPackage(nsCallObj_2))));      //test OK case

ASSERT_AND_LOG((CTraverseEnum<NonSeqEnumRange,false>::applyFrom<NS_Val_5>(NS_Val_3,Template_Mem_Callback_Obj(CNonSeqEunmInterface_2,NonSeqEunm,apply),makeParamPackage(nsCallObj_2))));     //test OK case

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::applyFrom<S_Val_1>(S_Val_3,Template_Mem_Callback_Obj(CSeqEunmInterface_2,SeqEunm,apply),makeParamPackage(sCallObj_2))));                  //test OK case

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,false>::applyFrom<S_Val_5>(S_Val_3,Template_Mem_Callback_Obj(CSeqEunmInterface_2,SeqEunm,apply),makeParamPackage(sCallObj_2))));                 //test OK case

#if defined(_MSC_VER) && (WINVER >= 0x0500)

#pragma push_macro("_Assert_Trigger")

#pragma push_macro("ChkExceptionThrow")

#undef _Assert_Trigger

#define _Assert_Trigger()

#undef ChkExceptionThrow

#define ChkExceptionThrow()

#endif //end defined(_MSC_VER)

ASSERT_AND_LOG((CTraverseEnum<NonSeqEnumRange,true>::apply(NonSeqEunm(NS_Val_Max+2),Template_Mem_Callback_Obj(CNonSeqEunmInterface_1 ,NonSeqEunm,apply),makeParamPackage(nsCallObj_1))));   //test Failure case because DemoEunm(NS_Val_Max+2) is not in
range

ASSERT_AND_LOG((CTraverseEnum<NonSeqEnumRange,false>::apply(NonSeqEunm(NS_Val_Min-2),Template_Mem_Callback_Obj(CNonSeqEunmInterface_1 ,NonSeqEunm,apply),makeParamPackage(nsCallObj_1))));  //test Failure case because DemoEunm(NS_Val_Min-2) is not in
range

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::apply(SeqEunm(S_Val_Max+2),Template_Mem_Callback_Obj(CSeqEunmInterface_1,SeqEunm,apply),makeParamPackage(sCallObj_1))));                  //test Failure case because DemoEunm(S_Val_Max+2) is not in range

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,false>::apply(SeqEunm(S_Val_Min-2),Template_Mem_Callback_Obj(CSeqEunmInterface_1,SeqEunm,apply),makeParamPackage(sCallObj_1))));                 //test Failure case because DemoEunm(S_Val_Min-2) is not in range

ASSERT_AND_LOG((CTraverseEnum<NonSeqEnumRange,true>::applyFrom<NS_Val_5>(NS_Val_3,Template_Mem_Callback_Obj(CNonSeqEunmInterface_2,NonSeqEunm,apply),makeParamPackage(nsCallObj_2))));      //test Failure case because traverse from NS_Val_5. (NS_Val_3
< NS_Val_5)

ASSERT_AND_LOG((CTraverseEnum<NonSeqEnumRange,false>::applyFrom<NS_Val_1>(NS_Val_3,Template_Mem_Callback_Obj(CNonSeqEunmInterface_2,NonSeqEunm,apply),makeParamPackage(nsCallObj_2))));     //test Failure case because reversed traverse from NS_Val_1.
(NS_Val_1 < NS_Val_3)

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,true>::applyFrom<S_Val_5>(S_Val_3,Template_Mem_Callback_Obj(CSeqEunmInterface_2,SeqEunm,apply),makeParamPackage(sCallObj_2))));                  //test Failure case because traverse from S_Val_5. (S_Val_3 <
S_Val_5)

ASSERT_AND_LOG((CTraverseEnum<SeqEnumRange,false>::applyFrom<S_Val_1>(S_Val_3,Template_Mem_Callback_Obj(CSeqEunmInterface_2,SeqEunm,apply),makeParamPackage(sCallObj_2))));                 //test Failure case because reversed traverse from S_Val_1. (S_Val_1
< S_Val_3)

#if defined(_MSC_VER) && (WINVER >= 0x0500)

#pragma pop_macro("_Assert_Trigger")

#pragma pop_macro("ChkExceptionThrow")

#endif //end defined(_MSC_VER)

}

#ifdef RUN_EXAMPLE_TRAVERSEENUM

InitRunFunc(showUsage_traverseEnum);

#endif  //RUN_EXAMPLE_TRAVERSEENUM

}

#endif // COMPILE_EXAMPLE_TRAVERSEENUM

#endif // __test_TRAVERSEENUM_h_

时间: 2024-08-27 16:17:29

15) .实现可变参数的(成员/非成员)模板函数的回调,消除类似代码的相关文章

volatile,可变参数,memset,内联函数,宽字符窄字符,国际化,条件编译,预处理命令,define中##和#的区别,文件缓冲,位域

 1.volatile:要求参数修改每次都从内存中的读取.这种情况要比普通运行的变量需要的时间长. #include <stdio.h> #include <stdlib.h> #include <time.h> void main() { time_t start, end; double res = 0; time(&start);  //获取时间,传递给start //volatile强制每次从内存读取 volatile int i; for (i =

C++ 11可变参数接口设计在模板编程中应用的一点点总结

概述 本人对模板编程的应用并非很深,若要用一句话总结我个人对模板编程的理解,我想说的是:模板编程是对类定义的弱化. 如何理解“类定义的弱化”? 一个完整的类有如下几部分组成: 类的名称: 类的成员变量(或属性,C#中属性和成员变量还是有区别的): 类的成员方法: 从编译器的角度看,我们必须明确指定以上3部分,才算完整地定义了一个类并且编译通过. 所谓的“类弱化”,是指类的设计者在定义类的时候,并没有完整定义一个类,而是把类的其中一部分的定义留给类的使用者. 从传统才c++98看,通过模板类,使用

[问题记录]Java关于可变参数重载问题

突然发现java的可变参数重载是存在歧义的,只是不知道java内部是怎么处理的,特意做如下实验: 测试代码如下: 1 /** 2 * Created by ieayoio on 16-3-1. 3 */ 4 public class VarTest { 5 6 public static void aaa(int ...a){ 7 System.out.println("可变参数重载"); 8 } 9 10 public static void aaa(int a){ 11 Syste

可变参数列表的实现

在学习C语言的过程中,大家是不是和我一样,认为printf是一个神一样的函数?他可以接受不同数目,不同类型的参数,他到底是怎么实现的呢? 让我们去看一下它的源代码: printf源代码: int printf(const char *fmt,...) { int res; va_list arg; va_start(arg,fmt); res = vprintf(fmt,arg); va_end(arg); return res; } 它采用的是可变参数列表,可变参数列表主要有以下两个缺点: 1

Python定义可变参数与list切片

一:如果想让一个函数能接受任意个参数,我们就可以定义一个可变参数: def fn(*args): print args Python解释器会把传入的一组参数组装成一个tuple传递给可变参数,因此,在函数内部,直接把变量 args看成一个 tuple 就好了. 二:list切片 取前N个元素,也就是索引为0-(N-1)的元素,可以用循环: xingqi=["微信","支付宝","apple","华为","星期一&qu

C 实现可变参数

C中可以借助va_list实现可变参数: va_start:使用传入的可变参数的第一个变量初始化va_list va_arg:获取当前可变参数,每次调用时会将指针向后移 va_end:结束 利用这个机制实现可变参数时,需要保证传入的参数可判断结束位置,即第一个参数用于控制结束,同时传入的参数必须得有这个参数作为结束. C可变参数的实现原理基于函数传参数的的栈,参数从右往左入??,通过第一个参数可以确定参数栈的位置,然后利用数据类型,配合结束符,可以将所有参数取出来. #include <stdi

可变参数列表

函数原型:列出了函数期望收到的参数数目及类型,但是它只能显示"固定数目"的参数. 可变参数列表:让一个函数在不同的时刻接受"不同数目"的参数.可变参数列表是通过宏来实现的,这些宏都在stdarg.h这个头文件中,所以使用可变参数列表时要引用头文件#include<stdarg>. 例如:求寻找一组整数中最小的值,因为整数的个数不确定,所以函数在传参的时候也是不确定的,因此需要用到可变参数列表: 利用可变参数列表求最小值:来看看可变参数列表的形式: int

【C语言】printf函数的简单实现(可变参数列表)

stdarg宏: 可变参数列表是通过宏来实现的,这些宏定义于stdarg.h头文件中,它是标准库的一部分.这个头文件声明一个类型va_list和三个宏va_start.va_arg和va_end.我们可以声明一个类型为va_list的变量,与这几个宏配合使用,访问参数. 声明一个va_list类型的变量arg,它用于访问参数列表的未确定部分.这个变量是调用va_start来初始化的.它的第一个参数是va_list的变量名,第2个参数是省略号前最后一个有名字的参数.初始化过程把var_arg变量设

jdk1.5新特性之-------&gt;可变参数

/* jdk1.5新特性之------->可变参数 需求: 定义一个函数做加法功能(函数做几个数据 的加法功能是不确定). 可变参数的格式: 数据类型... 变量名 可变参数要 注意的细节: 1. 如果一个函数 的形参使用上了可变参数之后,那么调用该方法的时候可以传递参数也可以不传递参数. 2. 可变参数实际上是一个数组对象. 3. 可变参数必须位于形参中的最后一个参数. 4. 一个函数最多只能有一个可变 参数,因为可变参数要位于形参中最后一个位置上. */ public class Demo4