在C++中侦测内嵌型别的存在(rev#2)

C++中侦测内嵌类型的存在(rev#2)

 

By 刘未鹏(pongba)

C++的罗浮宫(http://blog.csdn.net/pongba)

 

动机(Motivation)

假设一所大学的注册系统提供了一个注册函数:

 

template<class T>

void Register(T person)

{

Register(person, typename T::person_tag());

};

 

而对于注册者有以下几种标识:

 

struct student_tag{};

struct teacher_tag{};

 

还有Register的几个供内部使用的重载版本:

 

template<class T> void Register(T p, student_tag){...} // 注册学生

template<class T> void Register(T p, teacher_tag){...} // 注册教师

 

并规定学生类一定要在内部typedef student_tag person_tag教师类typedef teacher_tag person_tag这样,当传给起初的那个Register的对象为学生类对象时typename T::person_tag()其实就构造了一个student_tag对象,从而激发函数重载,调用Register内部版本的template<class T> void Register(T p, student_tag)版本。其他情况亦均有对应。这是泛型编程里的常用手法(静态多态),STL里屡见不鲜。

 

问题是,现在学校里假如不止学生教师,还有工人,警卫等其它人员。如果他们不会在类内部typedef任何东西,则Register需要一种机制以确定T内部是否typedef了某个标识符例如person_tag。如果没有,就默认处理。如果有,则再进行更详细的分类。

 

实现(Implementation)

这个问题可能有两个实现途径。

 

一是利用函数重载,具体如下:

 

typedef char (&yes_type)[1]; // sizeof(yes_type)==1

typedef char (&no_type)[2]; // sizeof(no_type)==2

 

以上的两个typedef用于识别不同的重载函数。char (&)[1]表示对char[1]数组的引用,所以sizeof(char(&)[1])==sizeof(char[1])==1注意围绕&符号的一对圆括号,它们是必要的,如果没有将会导致编译错误,正如char* [1]将被解析为char*的数组,char& [1]将被解析为引用的数组,而后者是非法的。将&用圆括号包围则改变了运算符的结合优先序,这将被解析为对char[1]数组的引用。

 

template<class T>

struct does_sometypedef_exists

{

template<class U>

static yes_type check(U, typename U::key_type* =0); // #1

static no_type check(...);

static T t;   // 声明

static const bool value = sizeof(check(t))==sizeof(yes_type);

};

 

注意,#1处,*=之间的空格是必要的否则编译器会将它解析为operator*=操作符。

 

在我的VC7.0环境下,以下测试是成功的:

 

struct A{};

struct B

{

typedef int key_type;

};

int main()

{

std::cout << does_sometypedef_exists<A>::value<<' '  // 0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值