第二章(技术)

1、编译器assert

#pragma warning(disable:4101)
//
///使用数组,无法传入额外参数
#define STATIC_ASSERT1(express) {char unnamed[(express) ? 1 : 0];} // 使用大括号是为了保证作用域,防止名字冲突


//
//使用类构造函数,同样无法传入额外参数方便上层调用者知道是在哪里
template<bool>
class CTestAssert2;


template<>
class CTestAssert2<true>{};
#define STATIC_ASSERT2(express) {CTestAssert2<express>();}


//
// 使用类构造函数参数,可以让上层传入字符串
template<bool>
class CTestAssert3;


// 为true时任意类型都能转换
template<>
class CTestAssert3<true>
{
public:
CTestAssert3(...);
};


// 为false时,使用编译器自动生成的默认构造函数,甚至没有构造函数
template<>
class CTestAssert3<false>
{
};


#define STATIC_ASSERT3(express,usermsg) \
{\
class Error##usermsg{};\
Error##usermsg tmp;\
sizeof(CTestAssert3<express>(tmp));\
}

void CTestThchniques::TestCompileAssert()
{
STATIC_ASSERT1(1);
//STATIC_ASSERT1(0);


STATIC_ASSERT2(1);
//STATIC_ASSERT2(0);


STATIC_ASSERT3(1, a);
//STATIC_ASSERT3(0, displayme);
}


2、常整数映射为类型,方便实现函数的重载

// 将整数映射成为一个类型
template<int v>
struct Int2Type
{
enum{value = v};
};
//
class CIsClone
{
public:
CIsClone* clone(){return NULL;}
CIsClone(){};


private:
CIsClone(const CIsClone& rhs);
};


class CNotClone
{
public:
CNotClone(const CNotClone& rhs){}
CNotClone(){}
};


template<typename T, bool bSupportclone>
class CTestInt2Type_Old
{
public:
void DoSomeThing()
{
T* pt = new T;
if (bSupportclone)
{
T* pNewObj = pt->clone();
}
else
{
T* pNewObj = new T(*pt);
}
}
};


template<typename T, bool bSupportclone>
class CTestInt2Type
{
public:
void DoSomeThing()
{
DoSomeThing(Int2Type<bSupportclone>());
}
private:
void DoSomeThing(Int2Type<true> a)
{
T* pt = new T;
T* pNewObj = pt->clone();
}
void DoSomeThing(Int2Type<false> b)
{
T* pt = new T;
T* pNewObj = new T(*pt);
}
};



void CTestThchniques::TestInt2TypeFun()
{

       //  被注释代码是无法编译通过的
//CTestInt2Type_Old<CIsClone, true> aa;
//aa.DoSomeThing();

//CTestInt2Type_Old<CNotClone, false> bb;
//bb.DoSomeThing();


CTestInt2Type<CIsClone, true> aa;
aa.DoSomeThing();


CTestInt2Type<CNotClone, false> bb;
bb.DoSomeThing();
}


3、型别对型别的映射

// 通过模板函数重载,解决无法偏特化问题
// 但是重载会导致参数传入的开销,可以通过Type2Type解决
template<typename T>
struct Type2Type
{
typedef T OriginalType;
};
//
// 这是一个重量级的参数,需要构造,拷贝,析构,
// 而它的作用只是根据类型来区分不同的函数重载
template<typename U, typename T>
T* Create_Old(const U& arg, const T& type)
{
return new T(arg);
}


template<typename U>
bool* Create_Old(const U& arg, const bool& type)
{
return new bool(arg);
}


// 这是一个轻量级的参数。但是它也足够满足区分不同函数重载的需求了
template<typename U, typename T>
T* Create(const U& arg, Type2Type<T> type)
{
return new T(arg);
}


template<typename U>
bool* Create(const U& arg, Type2Type<bool> type)
{
return new bool(arg);
}

void CTestThchniques::TestType2TypeFun()
{
bool* bc = new bool(true);


string* stra = Create_Old("abc", string());
bool* ba = Create_Old(true, bool());


string* strb = Create("abc", Type2Type<string>());
bool* bb = Create(false, Type2Type<bool>());
}


4、型别选择,根据参数选择适当的类型

// 根据flag控制Result类型,适合bool类型区控制类型
template<bool flag, typename T, typename U>
struct Select
{
typedef T Result;
};


template<typename T, typename U>
struct Select<false, T, U>
{
typedef U Result;
};


//
template<typename T, bool bIsClone>
struct TestTypeSelect
{
typedef typename Select<bIsClone, T* ,T>::Result ValueType;
ValueType aa;
};


5、编译器检测可转换型和可继承性,运行期检测使用dynamic_cast

template<typename T, typename U>
class CConversion
{
typedef char Small;
class Big
{
char dymmy[2];
};


static Small Test(U);
static Big Test(...);
static T MakeT();
public:
// 如果MakeT的类型为T能够转换为U,就会返回sizeof(Small)了,这样值就是1,不能转换就会返回Big了
// 依赖于编译器的函数重载
enum
{
TCanConversionU = sizeof(Test(MakeT())) == sizeof(Small), // T是否能转换为U
CanConversion2Way = TCanConversionU && CConversion<U, T>::TCanConversionU,// 是否能相互转换
};


enum
{
SameType = false
};
};


template<typename T>
class CConversion<T, T>
{
public:
enum
{
TCanConversionU = 1,
CanConversion2Way = 1,
}


enum
{
SameType = 1
};
};




// T是否继承自U或则两者是同一种类型,并且U不能使void*,因为任何类型都可以转换成void*
// 加const是为了防止类型传入const而转换失败
#define TIsBaseFromU(T, U)\
(CConversion<const T*, const U*>::TCanConversionU)\
&& (!CConversion(const U* ,const void*>::SameType))


//class CConversion
//{
// typedef char Small;
// class Big
// {
// char dymmy[2];
// };
//
// static Small Test(double);
// static Big Test(...);
// static int MakeT();
//public:
// enum{CanConversion = sizeof(Test(MakeT())) == sizeof(char),};
//};


6、type_info


7、NullType和EmptyType

class NullType;只有声明,没有定义,是一个标记位置,不能使用的

struct Emptytype{};


8、Type Traits

类型判断,识别。通过模板特例化可判断其类型,获取其类型

template<typename T>
class CTypeTrains
{
private:
 //
 template<class U>
 struct PointerTraits
 {
  enum{result = false};
  typedef NullType PointeeType;
 };

 template<class U>
 struct PointerTraits<U*>
 {
  enum{result = true};
  typedef U PointeeType;
 };
 //
 template<typename U>
 struct PToMTraits
 {
  enum{result = false};
 };

 //template<typename U>
 //struct PToMTraits<U::*>
 //{
 // enum{return = true};
 //};
 //
 template<typename U>
 struct UnConst
 {
  typedef U Result;
 };
 template<typename U>
 struct UnConst<const U>
 {
  typedef U Result;
 };
 //
 template<typename U>
 struct RefrenceTraits
 {
  enum{result = false};
 };
 template<typename U>
 struct RefrenceTraits<U&>
 {
  enum{result = true};
 };
public:
 enum {isPointer = PointerTraits<T>::result};
 enum {isMemberPointer = PToMTraits<T>::result};
 enum {isRefrence = RefrenceTraits<T>::result};
 typedef typename PointerTraits<T>::PointeeType PointeeType;
 typedef typename UnConst<T>::Result NonConstType; // 去除const,如果T传入的是const类型,而我们又需要申明T类型进行改变时的做法
};

另外loki库中的类型识别还支持函数指针类型识别,成员函数指针类型识别。这两个语法比较特殊,举例如下

函数指针

template <typename T>
        struct IsFunctionPointerRaw
        {enum{result = 0};};

        template <typename T>
        struct IsFunctionPointerRaw<T(*)()>
        {enum {result = 1};};

        template <typename T,
            typename P01>
        struct IsFunctionPointerRaw<T(*)(P01)>
        {enum {result = 1};};

        template <typename T,
            typename P01, typename P02>
        struct IsFunctionPointerRaw<T(*)(
            P01, P02)>
        {enum {result = 1};};

成员函数指针

template <typename T>
        struct IsMemberFunctionPointerRaw
        {enum{result = 0};};

        template <typename T, typename S>
        struct IsMemberFunctionPointerRaw<T (S::*)()>
        {enum {result = 1};};

        template <typename T, typename S,
            typename P01>
        struct IsMemberFunctionPointerRaw<T (S::*)(P01)>
        {enum {result = 1};};

        template <typename T, typename S,
            typename P01, typename P02>
        struct IsMemberFunctionPointerRaw<T (S::*)(
            P01, P02)>
        {enum {result = 1};};


// 有些参数是...类型的,如printf

template <typename T, typename S>
        struct IsMemberFunctionPointerRaw<T (S::*)(
            ...)>
        {enum {result = 1};};

        template <typename T, typename S,
            typename P01>
        struct IsMemberFunctionPointerRaw<T (S::*)(
            P01, ...)>
        {enum {result = 1};};

        template <typename T, typename S,
            typename P01, typename P02>
        struct IsMemberFunctionPointerRaw<T (S::*)(
            P01, P02, ...)>
        {enum {result = 1};};

// 有些参数是volatile类型。另外还有一些是const类型(函数类型是const)

template <typename T, typename S>
        struct IsMemberFunctionPointerRaw<T (S::*)() volatile>
        {enum {result = 1};};

        template <typename T, typename S,
            typename P01>
        struct IsMemberFunctionPointerRaw<T (S::*)(P01) volatile>
        {enum {result = 1};};


// 是否是类的成员变量

template <class U> struct PToMTraits
        {
            enum { result = false };
        };
       
        template <class U, class V> struct PToMTraits<U V::*>
        {
            enum { result = true };
        };
       
        template <class U, class V> struct PToMTraits<U V::*&>
        {
            enum { result = true };
        };


使用举例

void CTestThchniques::TestTypeTraits()
{
 bool isPtr = CTypeTrains<int>::isPointer;
 bool isPtr2 = CTypeTrains<vector<int>::iterator >::isPointer;
 bool isPtr3 = CTypeTrains<int*>::isPointer;
 
 const int i = 10;
 CTypeTrains<int>::NonConstType j = 10;
 j = 20;
 //i = 20;

 bool b1 = CTypeTrains<int>::isRefrence;
 bool b2 = CTypeTrains<int&>::isRefrence;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值