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

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

编辑:说三道四文库 发布时间:2018-01-18 04:11
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,竟没读懂。。。。
云雀科技:飞行器+地图,展望飞行器的新体验 Sandstorm,前Googler和极客名人建立通用开源工具保姆 触控科技CEO陈昊芝:引擎技术推动行业升级 谁能成为Hero,这一次你说了算!——TCL智能电视开发大赛创意阶段评审征集 微信官方在“公开课”上13个热点问题的解答摘要 vc中资源问题。 Windows2000的用戶權限 关于VB中引用DirectX的一个问题 一个日期加上任意天数得到另一个日期的算法 搞不懂的事?请各位帮助 请介绍一本C++的书,有利于初学着的.谢谢 求题目 widows server2003进程分配问题+ADSL上网?? widows server2003进程分配问题+ADSL上网?? the taiwan earthquake全文翻译 英语初二上第八单元reading翻译the tai the taiwan earthquake 的课文 英语翻译The (填一个单词)(提示:the mo 英语翻译牛津8A的,要全. 1999年9月21日台湾的这场地震造成了什么影响 1999年9月21日台湾的这场地震造成了怎样的影响 我国台湾省多地震的原因是( )A地形复杂多样 B属 台湾为什么多火山地震 快递哥邱师傅倒在送货路上 同行前去凭绍兴印染温州电镀两个“污染大户”转型温州双岙村遭垃圾围堵 焚烧垃圾引消防爱心的哥贵师傅往返江山衢州送尿毒症患思鑫坊曾是杭城近代建筑代表 如今成无炒股亏50%和赚50%的差距就在这里有舍才有得,新的一年,新的起航!黄金暴跌:全球可能都面临一场货币与财张士诚: 元末盐枭的兴亡之路专访世行集团副行长:中国同行工作效率情圣物语一指擎天灭晋被遗忘国度之暗夜精灵绝对良医西江旅游巢湖旅游乳山旅游乌兰察布旅游锡林郭勒旅游
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘