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

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

编辑:说三道四文库 发布时间:2017-07-23 10:46
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,竟没读懂。。。。
VB剪贴板的用法 VB开发CAI软件的小经验 VB软件设计中的几个问题 VB新手常见问题解答 VB修改注册表一特例 VB与VC混合编程中处理消息的方法 VB中的进制转换是怎样的? VB中调用带参数存储过程的实现(数据库) VB中感叹号“!”与圆点“.”的用法差异 VB中如何实现注册表的读写 VB中实现“擦视”技术 Visual Basic 2000年问题 Visual Basic 的未来 Visual Basic 命令分类表 Visual Basic三级跳 Visual Basic使用技巧 Visual Basic中的子类处理技术 Visual Basic中软件封面技术探秘 VisualBasic 软件设计中的几个问题 Windows 95/NT 运行了多长时间 -VB资料 Windows 的登录资料库 -VB资料 把回车键变成TAB键-VB资料 把文件置入到Text或RichText中 -VB资料 避免按 [ENTER] 回车键产生的“嘀”声 -VB资料 避免使用全局变量-VB资料 避免装载多份应用程序-VB资料 不定个数的参数 -VB资料 不在任务栏中显示,只能在Ctrl+Alt+Del对话框中显示或者干脆什么也不显示数 -VB资料 处理 Dropdown List型 Combo的录入问题-VB资料 VB创建和删除快捷方式 从程序中生成 exe 文件 -VB资料 大家开发界面使用什么,有多少人使用Swing,觉得优势是什么? kodak控件为什么不能在xp下用 printf 函数中 %p 是什么意思? vb.net如何执行外部命令 ***List Control 控件怎么编辑子项??200分重谢!!*** VB 如何开发在IE中可以直接下载安装的ActiveX控件? 大虾,我还该学什么?散分 do form 怎麼偉參數啊? 在 form 中又自私用啊? 請大家指教,謝謝!! 在系统权限中,create any table 和create table 我搞不清,查了书本也是迷糊,请帮我解释一下! 如何让BCB运行时不自动创建一个新工程? 问题青年来了 : 怎么把一个Win32 Application 改成ActiveX啊?解决了给你100分 新装宽带,征集防火墙方案 垃圾收集 在什么时候发生? 一个数据备份与还原路径合法的问题(50分)在线等待 将字符串中第i个字符删除? 什么函数返回ASCII码的对应的字符 Rose中Class Diagram中的几种类,我不清楚阿 给我一点对perl/python的初步认识 真有这样的事? 如何对jpg文件进行像素处理? 如何用正则表达式不区分大小写的匹配“<script ...>...</script>”? 为啥我得机器不能access 请教一个简单的问题 这样为什么不能加入记录,怎样加 请问,我想用两台2000共用一个ip上网,一个做iis服务器,另外一个做传奇的服务器。谁知道怎么做啊。 菜单拖动事件 使用TCP/IP编程是怎么一回事? 珊珊艾的玉照放出来啦!! 语句extern "C" AFX_EXT_API int WINAPI ExecSQL( CString strSQL ); 怎么理解?关键字AFX_EXT_API有何用? 急,怎么将String中的"/"替换成"\"? 四川的分数出来了吗? 关于MSFlexGrid的一个问题 高分求购经典旧书配本源码 《Windows编程指南》,清华出版社,成功后立马送分 关于百度插件问题 怎样用Request.QueryString("k")的值和select pass from c while pass=44的结果比较 关于在QR中横向打印的问题........... 为什么有的网站明明是用了数据库,但是网页文件却是.html的? 如何实现数据库中的图片存储 select ???? 这怎解决啊,Help!!!! 如何将结构相同的两表的数据合并? 建立一个简单的网上直播服务器需要那些步骤? 请教一个关于属性页的问题 可以这样查询吗 ?请问怎么出现设置目录的对话框,并且把路径保存edit中!!急急急急急急急(lxjgyl82) 关于监考管理 怎么通过ado动态的连接数据库 web服务器控件和html服务器控件有什么区别 合肥工業大學爆发學潮 Java程序监听数据库的操作 串口 小七狂捏爸爸脸蛋 万人迷任女儿摆弄(受不了良心谴责 埃及窃贼自惩任火车辗潘基文称涉日本历史认识发言“没有单指罕见海牛物种重现巴西海域 上次出现在美国加州已控制三成山火 或可于三周内默克尔将坚定支持盟友 同时确保德国不潘基文:对于涉历史言论遭日方误解感到叙利亚反对派称军方大部分已从指挥总部美媒评十大最危险工作 伐木业因死亡率英议会将就对叙干预投票表决 政府同意拉美太平洋联盟一体化迈出大步 四国就玻利维亚总统要求巴西遣返出逃议员默克尔称幼年时曾经遭遇过自行车被盗(普京与伊朗总统通电话探讨用政治外交手韩国向联合国提交东海大陆架划界信息 潘基文称涉日本历史认识问题发言“没有美媒评十大最危险工作 伐木业因死亡率津巴布韦一男子因用总统竞选海报当厕纸英议会将就对叙干预投票表决 政府同意潘基文称涉日本历史认识问题发言“没有普京与伊朗总统通电话探讨用政治外交手政协委员热议广东供给侧结构性改革:提李登辉办公室否认李欲组本土派政党传闻台湾南投近10名死者坟墓被盗 损失逾开局十三五 习近平为依法治网再加码“伴随成长”打造家庭教育指导《界别圆桌汇》推出30期:科技创新助黑龙江农业生产资料价格稳中有降《2015年四川省知识产权保护状况》政协委员:供给侧结构性改革要让消费者广东省政协委员热议供给侧结构性改革:广东“闯关”供给侧改革 科技创新要做不想给儿女们添麻烦 88岁老奶奶街头崔玉英会见新西兰自然历史公司董事长大桂东北大部江河将出现明显涨水过程1g箭毒蛙毒能杀死1.5万人,是真的不被注意的手机使用小习惯,或许会对你“金华OV”连续三个月稳居中国市场前谷雨夏未至 注意这两大养生原则别贪凉高手 | 埃德加·赖特勤敷面膜皮肤还是不好?这样做事半功倍专家解析:脊膜膨出的病因病理
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘