返回   cpper编程论坛 > C/CPP/TMP/GP
注册账号 论坛帮助 会员列表 日历事件 搜索 今日新帖 标记版面已读

回复
 
LinkBack 主题工具 显示模式
  #1 (permalink)  
旧 2006-11-20
初级会员
 
注册日期: 2006-11-20
帖子: 6
holyfire 正向着好的方向发展
默认 如何获得member field的type

比如有某个结构
struct X
{
type A;
};

给出X和A
想知道type的类型
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #2 (permalink)  
旧 2006-11-20
liuxinyu 的头像
高级会员
 
注册日期: 2006-02-09
帖子: 311
文章: 49
liuxinyu 正向着好的方向发展
默认

引用:
作者: holyfire
比如有某个结构
struct X
{
type A;
};

给出X和A
想知道type的类型
一般来说,在运行时比较难做到。否则就有非常方便的C++反射库了。
但是在编译期这个非常容易实现。可以参见boost::mpl,或者C++ template meta programming。

如果你仅仅是自己调试你可以使用std::typeinfo,这个RTTI可以给你一些hint,但是不同编译器,给出的结果不一样。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #3 (permalink)  
旧 2006-11-20
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

没typelist之类的手工写的东西,得不到的吧
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #4 (permalink)  
旧 2006-11-20
初级会员
 
注册日期: 2006-11-20
帖子: 6
holyfire 正向着好的方向发展
默认

我就是编译期间想知道,目前是用宏来实现的,而且代码很丑陋,想知道用mpl之类的有什么好的办法
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #5 (permalink)  
旧 2006-11-21
liuxinyu 的头像
高级会员
 
注册日期: 2006-02-09
帖子: 311
文章: 49
liuxinyu 正向着好的方向发展
默认

引用:
作者: holyfire
我就是编译期间想知道,目前是用宏来实现的,而且代码很丑陋,想知道用mpl之类的有什么好的办法
举个简单例子:
c++ 代码:
  1. #include <iostream>
  2.  
  3. //test case 1
  4. struct X{
  5.     int a;
  6. };
  7.  
  8. //test case 2
  9. struct Y{
  10.     float a;
  11. };
  12.  
  13. template<class T> struct is_int{
  14.     static const int value = false;
  15. };
  16.  
  17. template<> struct is_int<int>{
  18.     static const int value = true;
  19. };
  20.  
  21. template<class T> bool isInt(T){
  22.     return is_int<T>::value;   
  23. }
  24.  
  25. template<class T> struct is_float{
  26.     static const int value = false;
  27. };
  28.  
  29. template<> struct is_float<float>{
  30.     static const int value = true;
  31. };
  32.  
  33. template<class T> bool isFloat(T){
  34.     return is_float<T>::value;
  35. }
  36.  
  37. int main(int argc, char* argv&#91;]){
  38.     X test1;
  39.     Y test2;
  40.     if(isInt(test1.a)){
  41.         std::cout<<"X::a is int.\n";
  42.     }
  43.     if(isFloat(test2.a)){
  44.         std::cout<<"Y::a is float.\n";
  45.     }
  46. }

程序输出:
$ g++ gettype.cpp
$ ./a
X::a is int.
Y::a is float.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #6 (permalink)  
旧 2006-11-21
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

我想holyfire要的是int这个类型,类似于typeof(test1.a) b = test1.a;
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #7 (permalink)  
旧 2006-11-21
liuxinyu 的头像
高级会员
 
注册日期: 2006-02-09
帖子: 311
文章: 49
liuxinyu 正向着好的方向发展
默认

引用:
作者: SpitFire
我想holyfire要的是int这个类型,类似于typeof(test1.a) b = test1.a;
这样的话,的确比较困难。因为test1.a这个表达式已经不是常量表达式了,而是一个运行时的变量。这样的写法也完全是运行时反射的写法,试比较下面两个写法:
c++ 代码:
  1. typeof(test1.a) b = test1.a//运行时类似发射的写法
  2. TypeOf<X::MemberType>::Result b = test1.a; //编译期写法
  3.  

其中

c++ 代码:
  1. template<class T> struct TypeOf{
  2.   typedef T Result;
  3. };
  4.  
  5. struct X{
  6.   typedef int MemberType;
  7.   int a;
  8. };
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #8 (permalink)  
旧 2006-11-21
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

我写的例子可能不对, test1.a是运行期的,他要的是一个类似的编译期的东西
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #9 (permalink)  
旧 2006-11-22
普通会员
 
注册日期: 2004-04-30
帖子: 62
TiGEr.zZ 正向着好的方向发展
默认

gcc有typeof扩展,下一代标准也会有
如果仅仅是需要到类型信息自动推导,可以使用tr1:tuple,只是你不能按名字索引字段,而是用序号引用。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #10 (permalink)  
旧 2006-11-22
liuxinyu 的头像
高级会员
 
注册日期: 2006-02-09
帖子: 311
文章: 49
liuxinyu 正向着好的方向发展
默认

把话题岔得深一点,
首先,我前面回答里面有个错误,应该是std::typeid,而不是std::typeinfo
例如
代码:
void main() { Derived* pd = new Derived; Base* pb = pd; cout << typeid( pb ).name() << endl; //prints "class Base *" cout << typeid( *pb ).name() << endl; //prints "class Derived" cout << typeid( pd ).name() << endl; //prints "class Derived *" cout << typeid( *pd ).name() << endl; //prints "class Derived" delete pd; }
但是这个正如前面所说,各个编译器给出的结果不一样。所以会有一些问题,例如下面的伪代码:
代码:
void save(Base* p){ saveName(typeid(*p).name()); } Base* load(){ string name = laodName(); if(name == "Derived1") return new Derived1(); if(name == "Derived2") return new Derived2(); ... }
有可能你在某个编译器上,运行都OK,结果拿到另外一个编译器上,他在Save的时候,typeid().name()返回"De_1"而不是"Derived1"。

其次说说类型系统,C++如此强的类型系统带来的优点多呢还是缺点多呢?如果C++中突然没有了类型,想想看,将是发生一些很有意思的事情。首先,模板突然没有用了,比如下面的函数模板:
代码:
template<class T> T add(T x, T y){ reutrn x+y; }
在无类型的C++中,就变成了
代码:
add(x, y) { return x+y; }
更严重的是容器类也完全抛弃了模板,比如:
代码:
coll = new list; coll.push_back(1); coll.push_back(new Point(1,2)); coll.push_back(new Complex(3,4)); ... for(it=coll.begin(); it!=coll.end(); ++it) cout<<"abs(x)="<<abs(*it)<<endl;
程序员可以对着未知任何变量,呼叫任何函数,例如x.func1()
如果变量x所属的类(注意,不是类型)没有定义func1,编译器就向x的父类找,找到了就调用,找不到就继续向上找,如果最终没有找到,就抛exception

这样的情形,其实并不新鲜,在许多脚本语言中,例如perl, python, ruby,以及smalltalk, LISP中这些都是司空见惯的。

但是C++采用了强类型,并且是静态强类型。结果是带领程序员们到了完全另一个世界。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #11 (permalink)  
旧 2006-11-22
初级会员
 
注册日期: 2006-11-20
帖子: 6
holyfire 正向着好的方向发展
默认

我确实想得到int这个类型

我现在的实现是
用模板函数推导,函数参数增加一个哑元辅助
但是要用宏来辅助

template <typename _Ty>
object_info make_object_info(const std:tring name , const _Ty * dummy = NULL );

这个dummy是不会去用的,目的就是为了推导出_Ty

使用的时候
#define MEMBER_FIELD_BASE(MEMBER,NAME) \
{ \
object_type * ot = NULL; \
desc.member_fields.push_back( make_object_info( NAME , &ot->##MEMBER ) ); \
}

其实也就是用一个哑元变量,来利用模板函数推导某个字段的类型

但是这样的代码很不通用,而且还是没有把类型取出来,只是用到了

局限性最大的就是他一定要用到代码实现,无法在只使用声明的阶段来确定,如果能做到只用声明,那就可以写出
TypeOf<X,X::a>::Result var;
这样的代码了
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #12 (permalink)  
旧 2006-11-22
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

能做到的只能是
typeof<X,1>::Result var;

X::a这个语法是通不过的
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #13 (permalink)  
旧 2006-11-22
初级会员
 
注册日期: 2006-11-20
帖子: 6
holyfire 正向着好的方向发展
默认

X::a这语法倒是有的,代表的是a在X内的偏移位置

你看这个实现

template<typename T>
size_t __member_offset_of(int T::* off)
{
return *(size_t*)&off;
}

#define MEMBER_OFFSETOF(TYPE, MEMBER) meta::__member_offset_of<TYPE>((int TYPE::*)&TYPE::MEMBER)

可以求出字段在结构内部的相对偏移位置
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #14 (permalink)  
旧 2006-11-22
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

这个语法我知道,只是说在这里是通不过的,不能作为模板参数

可以实现一个typeof

template<typename T>
struct TypeStore
{
typedef T Type;
};
template<typename T,typename MemberType>
TypeStore<MemberType> typeof(MemberType T::* member)
{
return TypeStore<MemberType>();
}
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #15 (permalink)  
旧 2006-11-22
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

目前在想办法拿到这个MemberType
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #16 (permalink)  
旧 2006-11-22
liuxinyu 的头像
高级会员
 
注册日期: 2006-02-09
帖子: 311
文章: 49
liuxinyu 正向着好的方向发展
默认

引用:
作者: SpitFire
目前在想办法拿到这个MemberType
这样是不可以的:
c++ 代码:
  1. template<class T> struct TypeObj{
  2.     typedef T Result;
  3. };
  4.  
  5. template<class T>
  6. TypeObj<T> type_of(T){
  7.     return TypeObj<T>();
  8. }
  9.  
  10. int main(int argc, char* argv&#91;]){
  11.     X test1;
  12.     type_of(test1.a)::Result b = test1.a;
  13. }
$ g++ gettype.cpp
gettype.cpp: In function `int main(int, char**)':
gettype.cpp:55: error: expected `;' before '::' token

因为type_of()返回的是一个object,你无法对着Object使用::,来获取类模板内定义的Result,甚至更进一步,这个实现更直观,但是不能通过编译:
代码:
template<class T> T type_of(T){ return T(); } void main(){ type_of(test1.a) b = test1.a; //this will not pass! }
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #17 (permalink)  
旧 2006-11-22
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

也不是完全不可以,sizeof操作符就可以

int a = sizeof(typeof(&test1::a));

但是模板就不行,看来语法关过不去啊

over
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #18 (permalink)  
旧 2006-11-22
liuxinyu 的头像
高级会员
 
注册日期: 2006-02-09
帖子: 311
文章: 49
liuxinyu 正向着好的方向发展
默认

引用:
作者: SpitFire
也不是完全不可以,sizeof操作符就可以

int a = sizeof(typeof(&test1::a));

但是模板就不行,看来语法关过不去啊

over
BINGO! 我刚才也想到sizeof了。但是sizeof和typeof(这个只有GNU编译器支持)比较特殊。也许能找到一个很trick的实现。但是该难题的本质是编译期的类型Class不是Object。否则C++真的可以实现反射语法中的x.class().instance()了。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #19 (permalink)  
旧 2006-11-22
liuxinyu 的头像
高级会员
 
注册日期: 2006-02-09
帖子: 311
文章: 49
liuxinyu 正向着好的方向发展
默认

另外给几个link

一个是gnu的增强RTTI实现,基本能够满足本问题的要求。下一代标准出来,估计就好了。
http://gcc.gnu.org/onlinedocs/gcc/Typeof.html

一个是目前boost::mpl给出的实现
http://www.codeproject.com/vcpp/stl/typeof.asp

最后一个是目前gnu的编译器的现状,typeof返回的是一个字符串。
http://www.mhatt.aps.anl.gov/dohn/so...ef/std-ts.html
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #20 (permalink)  
旧 2006-11-22
pongba 的头像
高级会员
 
注册日期: 2004-09-02
帖子: 116
文章: 1
pongba 正向着好的方向发展
发送 MSN 消息给 pongba
默认

这是个很老的问题了,问题的实质规约到底其实就是在现有的C++里面实现一个typeof设施来。好几年前一帮人在CSDN上就讨论过,印象中有ajoo,不过后来证明是不可行的,我当时也绞尽脑汁想了很久,意识到只有通过sizeof来对类型信息进行编码,然后再解码出来才是解决之道,但是就到这里,发现走不下去了,其实走得下去,只不过问题是没法实现一个完全通用的typeof来。比如吧:

template<int N>
struct size
{
char dummy_[N];
};

template<typename T>
size<sizeof(T)> typeof_imp(T);

template<>
size<10> typeof_imp(int);

template<int size_>
struct type_of;

template<>
struct type_of<10>
{
typedef int type;
};

#define TYPEOF( e) type_of<sizeof(typeof_imp( e))>::type
然后提供一个REGISTER宏,让用户来REGISTER自定义的类型,比如:
#define REGISTER_TYPE(T) \
template<> \
size<GEN_UNIQUE_NUM(T)> typeof_imp(T); \
template<> struct type_of<GEN_UNIQUE_NUM(T)> \
{ typedef T type; };

这么一来,便实现了一个初级的”类型编码-还原“的框架。
REGISTER_TEMPLATE的实现大抵类似。

用的时候,只要先REGISTER你的自定义类型,如:
struct MyC{};
REGISTER_TYPE(MyC)

然后后面就可以对任意的类型为MyC的表达式用:
TYPE_OF( e)
了。

这个方案最大的缺点在于,它无法将一个复杂的类型分解为已知类型并各自推导,比如说,当它能够识别C和int的时候,无法让它能够自动识别出C<int>,你只能自行的再次REGISTER一下。这很不方便。因为类型的组合是无穷的。

于是卡在这里想不下去了

直到发现BOOST_TYPEOF...茅塞顿开...
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
回复

书签

主题工具
显示模式

发帖规则
不可以发表新主题
不可以发表回复
不可以上传附件
不可以编辑自己的帖子

启用 BB 代码
论坛启用 表情符号
论坛启用 [IMG] 代码
论坛禁用 HTML 代码
Trackbacks are 启用
Pingbacks are 启用
Refbacks are 启用



所有时间均为格林尼治时间 +9。现在的时间是 08:48 AM


Powered by vBulletin® 版本 3.7.0
版权所有 ©2000 - 2009,Jelsoft Enterprises Ltd.
(C) Copy Right All Right Reserved 2001 - 2007

Search Engine Friendly URLs by vBSEO 3.1.0