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

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

编辑:说三道四文库 发布时间:2017-02-22 02:22
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,竟没读懂。。。。
苹果面临一问题:正源源不断地失去优秀工程师 初学编程者必知的五个网站 大数据基准测试专题论坛:基准测试是一把尚未完成的尺子 大数据应用(下):应用驱动技术,DaaS创造价值 大数据研究与发展专题论坛:大数据在各领域中的应用及发展策略 雅虎新目标:欲收购照片分享网站Imgur 移动开发工具访谈《近匠》第01期:七牛云存储—BaaS进化论 ShareSDK:A轮融资到位!将推社会化评论SDK 70美元,你也能用Raspberry Pi做个专属iBeacon基站 7个鲜为人知却超实用的PHP函数 从管理远程式团队和分布式团队中所获得的宝贵经验 Netflix开源数据流管理器Suro Google新创意:天花板加麦克风 人脑植芯片 苹果获弯曲屏新专利 可给手机弄个大波浪卷 真正的跨平台硬件测试:3DMark已打通PC、iOS、Android 将Chrome浏览器变成终端工具 【开源推荐】AllJoyn:打造全球物联网的通用开源框架 21张图带你走进Google数据中心 Snapchat C轮融资5000万美元 投资方是Coatue Management 又一个被谷歌寄生的平台,Chrome应用启动器现来到OS X上 雷军遇上刘德华:创业、艺术、移动互联网 为了抗衡Android,传微软开始考虑WP和WinRT免费 维护代码库的五个精华实践 微软发布安全补丁 IE11.0.2随之而来 Qt 5.2正式版发布 全面支持移动平台 如何节约手游制作成本?揭秘CocoStudio编辑器强悍功能 市场竞争白热化:三大云服务商上演双十二“三国杀” UCloud联手盛科实现SDN硬件应用 AWS,还有多远? Instagram推新私信功能Direct:支持照片、视频和文本信息 微软CEO鲍尔默最后一次受访:我的正确决定远远大于过错 我机器里,98,2000装在C盘,XP装在D盘,现在我想只留下XP,不知道该怎么处理???????????????????????????? 如何实现5M以上的文件的上传 从windows进入unix Oracle 中文输入 是否onkeypress和onkeydown不能同时使用呀? Delphi 5下要做一个多 Y 轴的曲线图形,如何实现? 哪有xteamlindows下载?? 万分感谢!!!!! borland 会不会出一个 C# Builder? 乱码,头大了,不知道为什么pb导入excel怎么办 数据统计问题,请大侠门帮忙!急急急!!! 求解ZModem通讯协议源程序----有谁用过CZModemCore 我也不知道对不对! 最高级的问题?搞一个专业的VC程序员基地~~~~~~ 在研究directshow filter的push模式的兄弟请进 800分+工资管理原代码,如何解决ActiveReports打印图片的一个很难题;否则我快下岗了 有两个问题,每题40分,马上给分!!!! 如何使用打印机? 在爱情方面谁能做到这一点? 谁有 file cutter v1.4的注册码? 有急用! 搞一个专业的VC程序员基地~~~~~~谁愿意加入????? 最新发现:原来C++Bilder的项目文件(.bpr)是XML格式的! 关于FAT32和NTSF的问题 如何用VC实现Email的发送? 800分+工资管理原代码,如何解决ActiveReports打印图片的一个很难题;否则我快下岗了! 搞一个专业的VC程序员基地~~~~~~需要网页制作高手!! ADO 的用法 m_pRecordset->Fields->GetItem(index)->GetName() 关于CRichEditCtrl的问题之二,取的当前可见行数? 请问在哪里下载IMAIL SERVER???各位帮帮忙!!! 高手请回答,ADO和BDE到底有什么区别,你选择谁?为什么? 高分求教!!!!!!!!!!!!!!!!怎样得到局域网上所有的机器名?(普通WINDOWS网络,用VB?,好象用WNET API可以的) 如何安装com.ibm.bridge2java.*这个包阿? 有人吗???求救! 你也许也会遇到这样的问题? 800分+工资管理原代码,如何解决ActiveReports打印图片的一个很难题!!! 大虾看过来. 一个access表一万条记录,想转到Mysql下(Mysql在Linux下)用什么方法和什么语言来做好? rs.CursorLocation=aduseclient是什么东西? 800分+工资管理原代码,如何解决ActiveReports打印图片的一个很难题! 简单SQL,免费送分! 用ASP如何上传文件,可以用组件。 谁知道怎么改运行中的程序的托盘图标???我用SysTray.ocx不能改? 新手提问,简单题目,大量给分~~~~~~~~~~ 如何使用getdispatch(), 800分+工资管理原代码,如何解决ActiveReports打印图片的一个很难题!! 关于在一个窗口中的多个数据窗口的问题 扔块砖头, 开个场子 。 ( yeti_lee ) 800分+工资管理原代码,如何解决ActiveReports打印图片的一个很难题;否则我快下岗了? To: baicolt(五岁的小新是我师傅) 有没有人用过Jcreator 如何在sql server 的查询分析器中用sql语句转到另一台机器上的数据库,同样了sql server的 李叔叔家种粮食作物8分之3公顷,种油料作物0.21公顷,种经济作物5分之1公顷.哪种面积大 一张地图的比例尺1比200表示图上的什么表示实际距离的 6吨等于多少克 某县耕地面积约80万公顷,2005年粮食作物与经济作物的面积比是7:3,到今年将调整为6 :4哪一种作物的生产规模扩大了,扩大了多少万公顷.请回答完整要算式并解答 一幅地图的比例尺是200:1,图上120厘米表示实际距离是()米一幅地图的比例尺是200:1,图上120厘米表示实际距离是( )米 一根绳子第一次用了全长的1/4,又用了5/2米,这时已用的/剩下的=2/3,绳子长多少米 5π等于多少 华北平原种植的粮食作物以什么为主 一根绳子第一次用去全长的1/5,第2次用去3/5米,两次共用去这根绳子的1/2.这根绳子长多少米? 5+5等于多少 华北平原的主要粮食作物是什么?1.水稻 2.大豆 3.高粱 4.小麦 上海到杭州的实际距离大约是150千米,在一副比例尺是1:3000000的地图上,两地之间的距离是多少厘米?随便帮我把答案算出 若大气压为1.01*10的5次要方Pa,水平屋顶面积为100平方米,则大气压对水平屋顶上表面压力为多少N 华北平原的主要粮食作物是? 在一幅比例尺为1:3000000的地图上量得上海到杭州的距离为5cm,把它改画在比例尺为1:5000000的地图上,上海到杭州的图上距离是多少厘米?(如果不会,不妨用方程试试!) 大气压多少Pa 你知道华北平原的人们种植的主要农作物有哪些?你的判断依据是什么? 在一幅比例尺是1比5000000的地图上,量的上海到杭州的距离是3.4厘米.上海到杭州的实际距离是多少? 一根绳子减去20%后又接上5米,比原来断20分之3,则现在绳子多少米 4*7等于多少? 在一幅比例尺是1:5000000的地图上,量得上海到杭州的距离是3.4cm.上海到杭州的实际距离是多少 等于几? 请问1mbar等于多少kpa 在一幅比例尺为1:3000000的地图上量得上海到杭州的距离为5cm,把它改画在比例尺为1:500000的地图上 总压为1个大气压的体系,含50%氧气和50%氮气.问氧气的压强为多少? 200磅等于多少KPA 700米 800米等于多少吨? 当氮气大量增加会改变空气吗?会影响大气压吗?吃的面包包装是那种充气式的,一撕开袋子气体唰得一下全跑了出来,袋子就变瘪了.上网查了一下,像薯片、面包这种充气式包装充的一般是氮气. 100升等于几千克 15米长的绳子,用去五分之二,还剩()米?一根绳子,用去五分之三米,还剩12米,这个绳子()米?一根绳子,用去四分之三,正好用去15米,还剩()米? 6升150兆帕的氮气等于多少大气压 5060克等于几千克几克 在一幅比例尺是1:8000000的地图上.量得A、B两地之间的距离是3厘米.A、B两地间的实际距离是().A.80千米 B.2400千米 C.240千米 容积为20升的钢瓶中,装有150个大气压的氧气,现将氧气在等温条件下分装到容积为5L的氧气袋中,氧气袋原来是真空的,要求每袋氧气均达到10个大气压,设分装时无漏气,则最多可装几袋 压强1Pa等于多少克的压力 一幅地图上的比例尺是1:2000000,把它改写成线段比例尺是( ),在这幅地图上量得A、B两地的距离是15厘米一幅地图上的比例尺是1:2000000,把它改写成线段比例尺是( ),在这幅地图 我这..是头虱 还是 狗狗的虱子?我家养狗狗,它总是挠痒痒,我也没太在意,后来我觉得我全身都养,就像是有虫子,但是什么都看不到,躺下的时候能听到耳边有"皮皮"声,那天,一洗澡,关水后能看到 如果空气中的氧气都没了那么大气压是多少为什么? 1200克等于几千克几克 一只小狗的重量等于6只鸡的重量,3只鸡的重量等于4只鸡的重量.一只小狗的重量等于几只鸭的重量? 有2根绳子共长63米,减去第一根的3/5和第二根的7/9,还余下共22米,第一根长多少米? 在一幅比例尺是1:200000的地图上,量得甲、乙两地距离20厘米.如果在另一幅地图上,甲、乙两地距离8厘米.另一幅地图的比例尺是多少 某农场种植粮食作物和经济作物面积的比是3:2,一直种粮食作物252公顷,两种作物一共种了多少公顷 一幅地图的比例尺是1:30000,说明图上距离是实际距离的什么,实际距离是图上距离 什么倍,图上1cm的距离表示实际距离( )m. 许伯伯承包了2公顷土地,他把其中一半用来种植棉花,棉花的种植面积是多少平方米?还有一道:一个储水器中装有2m³纯净水,如果把这些水分撞到容积为10升的水桶中,可以装多少桶? 如图是红星农场农作物种植面积的统计图,回答下列问题:(1)若已知有250公顷土地种植蔬菜和棉花,则小麦有多少公顷?(2)若已知种植小麦的面积比种植蔬菜的面积多120公顷,则种植总面积 下面是某农场各种农作物种植面积的统计图,看图回答问题:己知粮食作物比经济作物多312公顷,这个农场一共有耕地多少公顷?三种作物各种植多少公顷?(粮食占总数的60%,其他作物占6%,经济 许伯伯承包2公顷土地,他把其中一半用来种棉花,棉花的种植面积是多少平方米? 下面是城东村今年各种农作物计划种植面积统计图.己知粮食作物的种植面积是175公顷,蔬菜种植面积是多少公顷?(粮食作物25% 蔬菜30% 其他45%) 一根绳子,第一次用去全长的15%,第一次用去全长的25%,还剩下8.4米.这根绳子原来长多少米?判断,打√,×.1、女生和男生人数的比是4:5,女生人数比男生少25%.( ) 2、甲数是乙数的2倍,那么甲 一根绳子长60米,第一次用去1/3,第二次用去1/4米,还剩()米 要过程 在比例尺为1:30000的地图上,实际距离是15千米,在图上应画多少厘米? 1pa等于多少公斤 一根绳子长100分米第一次用去3分米;第二次用去40分米;还剩多少米 某地的大气压为1.0*10^5Pa,这个大气压可以支持多高的水柱?要写出计算过程``! 1pa等于多少牛每平方米 一条绳子长15分米,第一次减去他的1/3,第二次减去它的1/2,还剩多少米 大气压在哪里为0 1pa等于多少每平方厘米多少克 7磅 多少克
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn