• 热门专题

C++模板:辨别函数类型

作者:  发布日期:2014-11-22 21:08:24
Tag标签:函数  模板  类型  
  • 在《C++ Template》中有一个辨识函数类型的模板技术,原文的例子貌似有些错误,这里做个对比验证,如有错误,请大家指出,原文的代码如下:

    template<typename T>
    class CompoundT {
    public:
    	enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 0, IsFuncT = 0, IsPtrMemT = 0 };
    	typedef T BaseT;
    	typedef T BottomT;
    	typedef CompoundT<void> ClassT;
    };

    这是基本模板,接着需要定义一个基本模板的特化,用于识别函数类型:

    template<typename T>
    class CompoundT<T()> {
    public:
    	enum { IsPtrT = 0, IsRefT = 0, IsArrayT = 0, IsFuncT = 1, IsPtrMemT = 0 };
    	typedef T BaseT();
    	typedef T BottomT();
    	typedef CompoundT<void> ClassT;
    };

    这个经过特化的类模板可以识别无参的函数类型,为了灵活使用,原文通过一个模板函数来完成具体的识别工作,如下:
    template<typename T>
    void test(T){
    	cout<<typeid(T).name()<<endl;
    	cout<<(CompoundT<T>::IsFuncT)<<endl;
    }
    这个模板函数到底能不能工作呢,我们可以实地验证一下:
    void fun(){}
    
    int main(){
    
    	test(fun);
    	return 0;
    }

    发现输出的结果如下:

    typeid(T).name() : PFvvE

    CompoundT<T>:: IsFuncT : 0

    显然,识别的结果是错误的,问题是出在test的定义上,注意到test的参数列表时(T),也就是说采用了传值方式,而如果传递的是函数,会发生decay,即将函数名称decay为函数指针,所以 T 被推断成了函数指针类型,而不是函数类型,所以上面定义的特化版本无法与之匹配。现在将test重新定义如下:(将T改成T&)

    template<typename T>
    void test(T&){
    	cout<<typeid(T).name()<<endl;
    	cout<<(CompoundT<T>::IsFuncT)<<endl;
    }
    
    再次执行相同的测试,结果如下:

    typeid(T).name() : FvvE

    CompoundT<T>:: IsFuncT : 1

    可见,这样就可以正确识别函数类型了。此外,我们也可以看到模板函数与模板类结合使用的巨大优势,因为模板函数可以进行类型推断(类型演绎)。如果不使用函数模板,CompoundT的作用就大大下降了,因为不能写成CompoundT<fun>,因为fun不是一个类型,fun相当于类型的实例。为了更加具体地说明这一点,我们可以进行如下定义:

    typedef void func();
    这样就可以使用CompoundT<func>了,因为func现在是一个函数类型。

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规