说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

关一个关于C++模板的问题

编辑:说三道四文库 发布时间:2017-01-22 04:09
HTML文档下载 WORD文档下载 PDF文档下载
现在我有一个接口,比如说是 
class ISupportInitialize
{
public:
    virtual void Initialize() = 0;    
}

然后有一个模板函数
template<class T> void function( T t );
 在函数中我想根据T是否从接口派生做一些不同的事,比如说T从ISupportInitialize派生,
我就调用 t.Initialize() 方法,否则就不调用。

请问题如何实现这样的功能
namespace __inner
{
    template<typename _T> char fun(_T*);
    template<typename _T> long fun(...);
}

template<typename _Base, typename _Sub>
struct is_same_type
{
    enum{value = sizeof(char) == sizeof(__inner::fun<_Base>((_Sub*)0)) };
};


class ISupportInitialize
{
public:
virtual void Initialize() = 0;
};

class Foo: public ISupportInitialize
{
public:
    virtual void Initialize(){ cout<<"Initialize"<<endl; };
};

template<bool>
class dispatcher
{
public:
    template<typename _T>
    dispatcher(_T& r){}
};

template<> class dispatcher<true>
{
public:
    template<typename _T>
    dispatcher(_T& r)
    {
        r.Initialize();
    }  
};

template<class T> void function( T t )
{
    (dispatcher<is_same_type<ISupportInitialize, T>::value>(t));           
}

int main()
{
   Foo x;
   int y;
   function(x);
   function(y);
}
template<typename _T> char fun(_T*);
template<typename _T> long fun(...);
第三次看到这个用法了,很是巧妙..
学习
学习ing
谢谢 Jinhao(辣子鸡丁·新年新气象) ,我现在正在看 Modern C++ Design 这本书,里面关于模板的介绍真是让人大开眼界。以后还要多向你请教 :)
>>template<> class dispatcher<true>
改成template<> class dispatcher<false>
为什么连编译都过不了, 请高手解释!(只要求能编译, 不管逻辑是否正确)

写的很好,佩服!
template<typename _T> char fun(_T*);
template<typename _T> long fun(...);
这个技巧到处都有,并不稀奇,但是整体封装的挺好的!
谁来答答我上面的问题
http://community.csdn.net/Expert/topic/4552/4552060.xml?temp=9.527224E-02
答案找到了...本贴的偏特化编译用得好!
全特化 -_-!
mark
呵呵,鸡丁好像很喜欢特化。佩服。

namespace __inner
{
    template<typename _T> char fun(_T & t){};
    template<typename _T> long fun(...){};
}

template<typename _Base, typename _Sub>
bool is_derived_from(_Sub & s)
{
    return sizeof(char) == sizeof(__inner::fun<_Base>(s)); 
}


class ISupportInitialize
{
public:
virtual void Initialize() = 0;
};

class Foo: public ISupportInitialize
{
public:
    virtual void Initialize(){ cout<<"Initialize"<<endl; };
};

void main()
{
    Foo f;
    if(is_derived_from<ISupportInitialize>(f))
             f.Initialize();

}
可以看看Boost提供的那些对于类型判断的模板,。
不过还是很佩服前面几位的代码。
利用模板偏特化可以实现
int main()
{
    Foo f;
    if(is_derived_from<ISupportInitialize>(f))
             f.Initialize();
}

其实这样来判断,这段代码就失去意义了。如果f没有Initialize,那么将导致一个编译错误
学习
(=_=)
真他们的越来越佩服鸡丁了 (=_=)
学习
#include<iostream>
using namespace std;

namespace __inner
{
template<typename _T> void  fun(_T*t){ t->Initialize();}
template<typename _T> void  fun(...){cout<<"...."<<endl;}
}
class ISupportInitialize
{
public:
virtual void Initialize() =0;
};

class Foo: public ISupportInitialize
{
public:
int i;
void Initialize(){ cout<<"Initialize:  "<<i<<endl; };
};


template<typename T>
void Proxy(T t)
{
__inner::fun<ISupportInitialize>(&t);
}
int main()
{
Foo x;
x.i=10;
int y=0;

Proxy(x);
Proxy(y);
}

唉,研究了一下,做了个变体出来,供参考
鸡丁啊......................(=_=)
SammyLan...你把要做的事情移到了fun里面 使得更直接一点. 但是有时可能太直接了也不便于扩展,或者另做它用.呵呵
其实这样来判断,这段代码就失去意义了。如果f没有Initialize,那么将导致一个编译错误
------------

NO, 如果本身f没有Initialize,它的基类也必须要有,否则在定义Foo f的时候就会因为包含了纯虚函数而出错,到不了后面判断的那一步。

所以基本上个人认为判断“Foo是不是ISupportInitialize”的派生类,就可以完成90%以上的“Foo有没有已实现的Initialize”的判断了,

我倒是觉得,如果是一个private 继承,似乎是没有办法了。但作为接口,private继承还是少的。
template<> class dispatcher<true>
{
public:
    template<typename _T>
    dispatcher(_T& r)
    {
        r.Initialize();
    }  
};

template<class T> void function( T t )
{
    (dispatcher<is_same_type<ISupportInitialize, T>::value>(t));           
}
-------------------------------
认真看了一下,其实这一段跟俺那一段不是等价的么?is_same_type<>::value得到true或者false,然后根据true/false决定是否调用t.Initialize()


不过你说的那个问题是对的,就是说,如果Foo本身没有实现Initialize(),但是其基类曾经实现过,比如:

class ISupportInitialize
{
public:
virtual void Initialize() = 0;
};

class Temp: public ISupportInitialize
{
public:
    virtual void Initialize(){ cout<<"Initialize"<<endl; };
};

class Foo: public Temp
{
};
 
这个时候就会很糟糕,换一种方式可能会好一些。

void main()
{
    Foo f;
    if(is_derived_from<ISupportInitialize>(f))
    {
        ISupportInitialize * pBase = &f;
        pBase->Initialize();
    }

}

什么是特化?
鸡丁兄。请教一下。。小弟看不明白
(dispatcher<is_same_type<ISupportInitialize, T>::value>(t));   
这里的外层括号的作用是什么??
(dispatcher<is_same_type<ISupportInitialize, T>::value>(t));
这里。相当于
dispatcher<is_same_type<ISupportInitialize, T>::value>  _dispatcher(t);
术语上我不知道要怎么解释。。但是外层括号的作用就是省掉定义一个对像

不知道我这样说正不正确。。
外层的括号可以去掉。

 xxxdg(学习中) 的代码
如果Foo 不是从ISupportInitialize派生,则你的程序编译会不通过。
 Jinhao的代码是利用了模板的一个特性:如果一段模板代码没有被用到,则它不会被编译。所以不会报编译借
(dispatcher<is_same_type<ISupportInitialize, T>::value>(t));
最外边这一层括号不能去掉
如果要去掉最外层的话,那么就必须这么写
dispatcher<is_same_type<ISupportInitialize, T>::value> _dispatcher(t);

其中上面这段和下面的等同
dispatcher<is_same_type<ISupportInitialize, T>::value> (_dispatcher)(t);

所以,如果去掉最外面层,
dispatcher<is_same_type<ISupportInitialize, T>::value>(t);
其实就是
dispatcher<is_same_type<ISupportInitialize, T>::value> t;

最后在来看看 function
template<class T> void function( T t )
{
(dispatcher<is_same_type<ISupportInitialize, T>::value>(t));
}
如果去掉最外层括号,那么就成了
template<class T> void function( T t )
{
  dispatcher<is_same_type<ISupportInitialize, T>::value> t;//t?重复定义!
}
MK
That is not important.
It is a never-committed crime.
---------------------------------
int main(int argc, char *argv[])
{
    Foo f;
    if(is_derived_from<ISupportInitialize>(f))
    {
        ISupportInitialize * pF = (ISupportInitialize *)&f;
        pF->Initialize();
    }        
    int k;
    if(is_derived_from<ISupportInitialize>(k))
    {
        ISupportInitialize * pF = (ISupportInitialize *)&k;
        pF->Initialize();
    }        
  system("PAUSE");
  return 0;
}
--------------------------------------------------
模板特化是好的,不过我个人认为像条件判断等一些基本语法,还是保留原始语法更好一些,显得简洁。编程风格的问题,Not necessarily. Any way,I have sent my ADMIRATION. :)
MK!
学习
ri.....
枉我自诩学过c++,熟练vc,竟没读懂。。。。
假如像招聘程序员那样租车…… CrowdStar:Windows Phone 8是开发者的下一片蓝海 腾讯云总经理陈磊透露流量变现计划 将比亚马逊AWS更专注 代码之美——Doom3源代码赏析 英特尔公布2012财年财报 Q4净利润同比下滑27% 谷歌CEO佩奇:创新重于竞争 关注非增量改进 再尝败绩 微软杀软AV-TEST反病毒认证失败 财富:2013最佳雇主 谷歌第一微软75苹果未入榜 移动应用注册表单必死! 数据:2012年的全球互联网知多少 访中粮我买陈伟伟:高并发大压力挑战架构师极限 左路Deep Learning+右路Knowledge Graph,谷歌引爆大数据 数据库排行榜:关系型居首,NoSQL整体人气最高 联通:要做PaaS,存储最低为TB 百度资深交互设计师谈微信4.5版本 TalkingData推出移动游戏数据分析平台 一周消息树:著名计算机黑客Aaron Swartz自杀身亡 使用Windows 8模拟器及Visual Studio 2012调试IE 10触控及响应式Web设计 Azure、AWS要来了 IDC抱团取暖还是各找出路 C#使用ICDBurn实现CD刻录 验证码识别基础方法及C#/.NET源码 傲逆软件CEO周鲁:核心游戏精神,在移动游戏创作中传承 Kim Dotcom推出新文件存储服务平台Mega 用户数一天达百万 美FCC:希望全美在2015年部署千兆以太网 iOS和Android双平台:帷千动媒SDK 3.0发布 移动周报:2013年移动App设计13大精髓 构建高可扩Web架构和分布式系统实战(下) API设计的十大最差和五大最佳实践 Hadoop:为什么RAID-0不行? 电子前沿基金会:实现互联网自由需翻越5座大山 安全无小事:2013年最令人期待的15家安全公司 还是老问题 redhat安装问题,请高手指点 网页中有一文本框,如何约束用户输入格式 现在fanso怎么回事? 安徒生童话之六---老爹做的事总是对的 (呵呵,好故事,很美丽) 如何调用EXE或DLL程序,使被调用程序是调用程序的MDI中的一个子窗口? 《网络设计师教程》P103表5.2中 4B/5B码和4位2进制之间是怎么转换的? COM进程类组件中,在一个接口中加了一个方法,成员变量类型CString,可是不行,那该用什么? 请问那里有 motif toolkit 开发工具下载 一个mysql的问题! 出售软件源代码以及销售权! byte类型的数据如何转化成二进制数,显示给用户(如8-》0000 1000) 代征:精通vc的深圳朋友,精通网络通讯的开发和多媒体处理。 20分求助!这条警告是什么原因呀?怎么解决 ?LINK : warning LNK4089: all references to "SHELL32.dll" discarded by /OPT:REF 局域网的文件共享传输是基于什么协议的? windows and dos ??? 请问大家几个技术问题!!谁能回答阿!比较着急!:) 有没有代替VB里的PICTUREBOX 的控件,VB里的不好用?????????? 我是新手,请问JSP有些什么开发软件?比如JAVA用JBUILDER。。。 请问知道整型值a=97,什么函数可以得到"a"呢?即97->"a"通过什么函数呢? 如何将十进制数转换成二进制数 函数对象的简单问题 喜欢仙剑的朋友请进。:) 恭喜恭喜? 我想制作C++ Builder4工程的安装程序,不知道用什么软件,请大家帮忙。谢谢! 请问大家几个技术问题!!谁能回答阿! 我是ASP初学者,请求一个简单的问题,Help!!! 有没有关于installshield6的书, 快看呀!我真的要不行了! 请教大家一个术语吧! 低手问题,关于Form中的数据问题,谢了。 如何用PictureBox控件显示GIF图?特急!!!!!! 单文档多视(急!) 想学delphi中关于database方面的内容,不晓得哪本书好,大家推荐好吧? “CSDN准备推出海外图书邮购服务,首批是侯捷的著作和译作” 什么时候可以开始? 谁能介绍一下嵌入开发领域比较成熟的产品?他们的功能、性能如何 关于Autocad字体的问题 在 ActiveForm 中如何初始本地数据模块!菜鸟问题! (const char *)&p转化为delphi语言该是什么? ####我拼了命也要问出这个问题的答案########## 怎样才可以描述点击窗口右上角的“x”时所发生的事件,请给个例子,谢谢了! 哪儿有Install anywhere 4下载 庆祝kylix2001,终于知道叫什么好了,耶………… VB,请问set obj=new class 和 dim obj as new class的区别????????? install anywhere 4 哪儿有下载? GGMM,向我灌水..... 如何截获视频卡串送过来的图像。 高级程序员,在weblogic上做j2ee开发半年多,jsp一年左右,求职。 那里有PB的反编译工具? ~~~~~~大家注意了: wjyasd(即使用FPE改了钱,也绝不能忘记艰苦朴素的优良作风) 这个帐号…… 关于动态连接与静态连接的问题,送分了!!! 文章中一句话的含义?高手进!白云深处吉普车行了两个多小时,终于登上海拔两千多米的燕山主峰玉皇顶.纵目四望,八百里燕山,一派磅礴气势.河北电视转播台高高的井架直插云霄.我们正看得 父爱的作文300字要写生病了爸爸照顾你,下午必要, 关于母爱和父爱的作文100字 大师风范这篇阅读,从大师的沉默中你体会到了什么 父爱作文300字,要描写最动情的一个瞬间!就是写一个动情的瞬间,不要太俗气了. 关于父爱母爱的作文 550--600字左右是的 大师风范阅读答案.2010—2011六年级的试题啊!照样子写词语 (技艺)高超 精彩的() ()高尚精湛的(琴艺) ( )高明 精致的()本文最后一句在写作方法上叫做 仅此一点3个含义中的第 求关于父爱的作文300字要精彩的 不要流水账 热牛奶的坚决不要 关于父爱母爱的作文350个字左右 大师风范阅读答案 苏教版啊 五年级下大练第三单元测试卷的那个啊 急QAQ原文:一位世界一流的小提琴演奏家在为人之道演奏时,从来不说话。每当学生拉完一曲,他总是再把这一曲再拉一 写父爱的作文300字,只要300字可以的加悬赏分 找一篇500字左右的作文《我心中的爱》关于父爱,母爱的. 大师什么是大阅读答案 这一刻,我感受到了父爱作文500字 关于父爱或母爱的200字作文200字,一定是200字左右!不用多!用动作描写或外貌描写, 请大师细腻翻译短文,题目也要翻译,谢谢 父爱作文 关于父爱母爱的作文500字左右 有奖励哦最好带有侧面描写哦!我不想要重复的哦!百度上能收到的我不要的哦!。。。(*^__^*) 嘻嘻……谢谢大家! 作文:一个令人感动的瞬间(体现父爱或母爱) 关于父爱的作文.老师让我们写一篇 有关于父爱的作文,要体现出父爱的伟大,要有真实感受要体现父爱的伟大,要有真实感受,自己不得少于600字. 感动作文的结尾快 “一个令人感动的瞬间”为题,写一篇作文,歌颂无私的父爱或母爱.要求有具体的细节 求作文:我深深感受到了父爱的伟大!初三的作文,600字! 《一件令我感动的事》作文结尾写汶川地震的事结尾怎么写今天要 描写父爱或母爱的好文章急! 有关父爱感觉描写的文章父爱感觉的,不要具体事例, 感动的作文 结尾关于母爱 如何写关于母爱和父爱的作文?要500字以上!写一件事!适合四年级! 父爱的作文500字 求一些关于父爱的作文的素材 去几个例子,别太复杂,很急,快 父爱母爱的好文章要不长不短,通俗易懂,直点中心. 求:关于写父爱的作文 800字 写父爱作文的素材有没有? 急需一篇描写父爱或母爱的感人好文章最好短一点(写作业要用),希望今晚就有~谢谢了~ 父爱的作文700-800字亲身经历 有没有关于父爱和母爱的文章,诗,素材和事例之类的 关于母爱和父爱的作文急需母爱或者父爱的作文,要通过一件事、一次批评等等,要在今天~ 关羽父爱的作文,800字 父爱 作文素材要你自身的,不要他人的.要新颖的,不要太俗的像关于生病被照顾的,下雨送伞的等等都不要 母爱或父爱的作文 写一篇有关父爱母爱的作文 800字的 如何理解课文的主要内容 -):-):-)求大师一一帮一帮 关于父爱或母爱的作文符合实际一点拉 求在父爱中成长的作文(800字) 民族风范的作文 有关父爱母爱的作文!……………………………… 关于感动的作文 800字 大师风范中小提琴家为什么说”琴声是最好的教育“? 父爱母爱作文 感动作文800字 大师风范中的小提琴家为什么说:琴声是最好的教育 关于父爱母爱的文章给哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥哥 以感动为话题的作文 800字 急要有叙事的内容 上个世纪初,有一个犹太少年,他做梦都想成为像帕格尼尼那样伟大的小提琴演奏家.他一有空就练琴,可是,就连他的父母都觉得这个可怜的孩子拉得实在太蹩脚了,完全没有音乐天赋.有一天,少 有关父爱母爱的文章快 关于母爱或父爱作文150字左右 曾经在一本杂志上看到过一篇这样的文章,给我的印象很是深刻,队长杰克带领着他的队友们正在日常的维护铁路的检修工作,天气很干燥,工作枯燥乏味,杰克在这条铁路上已经工作了15年了,所 父爱300字作文我说的是父爱,而且一定要300字左右 我懂得了(母爱或父爱) 作文600字
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn