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

回复
 
LinkBack 主题工具 显示模式
  #1 (permalink)  
旧 2004-07-19
高级会员
 
注册日期: 2002-09-15
帖子: 2,531
ajoo 正向着好的方向发展
默认 怎么实现这个trait?

我要写这样一个Trait.
代码:
template<class T, class A, class B> class Invoker{ void invoke(A& a, B& b){ T::apply(a,b); } };
关键的问题是:我不知道T::apply是否接受const B&或者是B&。

我希望我的Invoker可以察觉这个constness,如果T::apply期望B&,而传入invoke()的正好是一个const,我做一个拷贝。
就这样:

B tmp;
T::apply(a,b);


如果知道T::apply是一个非模板的函数,并且没有overload,那么,我可以用函数指针&T::apply,然后用经典的sizeof的trick来找到B是const还是什么。

但是问题是T::apply可能是一个模板函数,它可能是:

代码:
template<class A> void apply(A& a, B& b);
可能是

代码:
template<class B> void apply(A& a, const B& b);
这时我怎么判断?如果直接调用apply,程序可能编译错误。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #2 (permalink)  
旧 2004-07-19
高级会员
 
注册日期: 2002-09-15
帖子: 2,531
ajoo 正向着好的方向发展
默认

例子有点小错误:

B tmp;
T::apply(a,b);
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #3 (permalink)  
旧 2004-07-19
高级会员
 
注册日期: 2002-09-15
帖子: 2,531
ajoo 正向着好的方向发展
默认

又错了!

例子有点小错误:

B tmp;
T::apply(a,tmp);
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #4 (permalink)  
旧 2004-07-19
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

ajoo是否可以考虑把apply变成functor呢,这样可以用偏特化来判断调用apply是使用const B&还是B&
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #5 (permalink)  
旧 2004-07-19
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

看来我理解错了,ajoo是要知道apply是否接收const B&
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #6 (permalink)  
旧 2004-07-19
高级会员
 
注册日期: 2002-09-15
帖子: 2,531
ajoo 正向着好的方向发展
默认

对,写成伪码就是:

代码:
if(constness(b)==Const && constness(F::apply(A,B), 2)!=Const){ B tmp(b); F::apply(a, tmp); } else F::apply(a,b);
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #7 (permalink)  
旧 2004-07-19
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

ajoo,你改一下apply,你原来是tempalte function,现在改成template functor,在里面typename 一下,比如这样
class T1
{
template<typename A,typename B>
struct apply1
{
typename A lhs;
typename const B rhs;
void operator()(A,const B);
};
apply1 apply;
};

class T2
{
template<typename A,typename B>
struct apply1
{
typename A lhs;
typename B rhs;
void operator()(A, B);
};
apply1 apply;
};

这样你的能判断T中的apply的参数是const B还是B
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #8 (permalink)  
旧 2004-07-19
jinfeng_wang 的头像
高级会员
 
注册日期: 2002-11-14
帖子: 117
jinfeng_wang 正向着好的方向发展
默认

如果实在不行,那就用adapter把apply封装一次吧。
这问题是不是归结到“成员模板函数无法特化”?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #9 (permalink)  
旧 2004-07-19
jinfeng_wang 的头像
高级会员
 
注册日期: 2002-11-14
帖子: 117
jinfeng_wang 正向着好的方向发展
默认

if(constness==Const && constness(F::apply(A,B), 2)!=Const){
B tmp;
F::apply(a, tmp);
}
else
F::apply(a,b);

//既然这样,那直接copy就可以了,为何还要判断呢?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #10 (permalink)  
旧 2004-07-19
高级会员
 
注册日期: 2002-09-15
帖子: 2,531
ajoo 正向着好的方向发展
默认

我也在想绕过的办法。但是问题是,这个F是个库外面的用户提供的类型。要求用户对自己的函数是否用了const额外声明一下感觉不好。

没有直接的办法了?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #11 (permalink)  
旧 2004-07-19
abp 的头像
abp abp 当前离线
高级会员
 
注册日期: 2002-08-30
帖子: 811
abp 正向着好的方向发展
默认

boost::function_traits::argN_type + boost::is_const
或许可以解决你的问题
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #12 (permalink)  
旧 2004-07-19
高级会员
 
注册日期: 2002-09-15
帖子: 2,531
ajoo 正向着好的方向发展
默认

呵呵。还是死活想不出办法。这时候就想:要是能catch compile-time exception就好了。我就直接调用一下,catch住这个exception然后看看是不是const T&到T&无法转换。

唉。这是关于那个smonde库的,如果可以做到这个,我想我就可以大幅提高效率,减少大多数的拷贝。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #13 (permalink)  
旧 2004-07-19
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

让客户写几个typename,把function变为functor,工作量不大,却能大大提高,如果我是这个client,我一定干
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #14 (permalink)  
旧 2004-07-19
高级会员
 
注册日期: 2002-09-15
帖子: 2,531
ajoo 正向着好的方向发展
默认

不行的。客户的代码可能是这样的:

代码:
template<class U, class M> void apply(U& u, M& m){ ... m.result(u); }
你让用户怎么写typedef?
只有真正拿到u和m对象的类型,才能理论上检查出传入const U是否可以。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #15 (permalink)  
旧 2004-07-20
高级会员
 
注册日期: 2003-11-11
帖子: 147
ilovecpp 正向着好的方向发展
默认

期望T&参数,你却给他一个tmp? well,为什么会需要这样的行为?这和把T()传给T&没太大区别呀。
至于brutal-force做法么,当然是用---traits,把责任推给用户。apply定义traits有困难?easy,可以要求class M对他的result方法再给traits么 最后就变成了每个对象都有一堆traits...所以ajoo你的语言里compile-time reflection一定要做全,至少不能比runtime的弱。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #16 (permalink)  
旧 2004-07-20
高级会员
 
注册日期: 2002-09-15
帖子: 2,531
ajoo 正向着好的方向发展
默认

呵呵。要是M也是

代码:
tempalate<class U> void result(U&){...}
呢?还怎么写traits?

要是M既支持const U,也支持non-const U,又怎么写?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #17 (permalink)  
旧 2004-07-20
高级会员
 
注册日期: 2002-09-15
帖子: 2,531
ajoo 正向着好的方向发展
默认

期待T&,为什么不能给tmp?

它只是需要一个U,有初始值,可以往里写东西,然后再把这个东西传递下去。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #18 (permalink)  
旧 2004-07-20
高级会员
 
注册日期: 2003-11-11
帖子: 147
ilovecpp 正向着好的方向发展
默认

引用:
作者: ajoo
呵呵。要是M也是

代码:
tempalate<class U> void result(U&){...}
呢?还怎么写traits?

要是M既支持const U,也支持non-const U,又怎么写?
呵呵,自然是继续把责任往外推
type_traits<M>::method_result::is_callable_with_arglist<cons<U,nil> >::value
这个模版大概又要依靠type_traits<U>。
说穿了就是编译期的concept checking框架,不同的是我们需要把checking的结果作为常量,而不是编译错误,所以必须完全用编译期结构。也就是说,要做完备的话,需要把全部的类型信息和推导规则都用meta-programming实现,然后每个函数描述自己的requirement(只需与编译相关的部分)。
完全不现实,just kidding
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #19 (permalink)  
旧 2004-07-20
高级会员
 
注册日期: 2003-11-11
帖子: 147
ilovecpp 正向着好的方向发展
默认

ajoo说的catch compile exception,对编译器可是一个大挑战,作者们从没想过需要从错误中恢复吧。C++ meta-programming本来就是meta-programme和programme混在一起,够头大的,现在又把编译过程这一层混进来...所以我想的是用type traits自己实现编译器的一部分,每个函数用这个语言表达特定调用能编译的条件,这样至少层次上挺清晰的。

还有个办法,把有多种选择的地方都标上预处理符号,用一个driver反复调用编译器来搜索能使程序编译通过的组合
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #20 (permalink)  
旧 2004-07-20
高级会员
 
注册日期: 2002-09-15
帖子: 2,531
ajoo 正向着好的方向发展
默认

解释一下我期望的框架:

用户实现一个rule:

它可以接受任意的Multiverse类型,因此不需要虚函数.

如果用户需要改变Universe的,就这样
代码:
template<class M> void apply(Universe& u, M& m){ ... u.change(); m.result(u); }
如果确认不需要改变Universe的,就这样:
代码:
template<class M> void apply(const Universe& u, M& m){ ... }
如果自己不改变,但是要把Universe传递下去的,就这样:

代码:
template<class U, class M> void apply(U& u, M& m){ ... m.result(u); }
Universe&是对caller说:
我要求能够改变Universe.如果你不在乎我改变它,你就直接把你的Universe给我.如果你不希望我改变它,你就做一个拷贝再传给我.

const Universe&对caller说:
我保证不改变你的Universe,你把它直接给我就是.

U&是对caller说:
我自己不改变Universe,但是如果你给我的M要改变它,我就没办法了.


对于caller来说,如果它有一个Universe对象,要传给某一个rule,但是还有其它分支等待执行,就不能允许现在这个分支改变这个Universe对象.
而如果没有其它分支了,只是顺序执行,那么我就不在乎你是否改变我的universe对象,反正我也用不着它了.

在我的处理分支的代码里是这样:
代码:
const U& u1 = u; P::apply(u1, m); Q::apply(u2, m);
这里有P和Q两个分支要走.走Q和P时,要保证入口的U的状态不变.

所以,我不能允许P::apply改变U的状态,而对Q我就不在乎了.


在tianxing wang的原来那篇文章里,是直接通过做拷贝来处理的:

代码:
U tmp = u; P::apply(tmp, m); Q::apply(u,m);
但是,此处如果P这个分支碰巧不需要改变U的状态,这个拷贝就是个浪费了.
而这种不需要改变的情况是很常见的,比如:

代码:
some<R>: sum<one, product<R, some<R> >{};
也就是:

代码:
some r = one | r >> some r
one这个分支要被执行很多很多次,但是它不改变universe的状态.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
回复

书签

主题工具
显示模式

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

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



所有时间均为格林尼治时间 +9。现在的时间是 07:40 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