zoukankan      html  css  js  c++  java
  • 让gcc支持成员函数模板的trick

    让gcc支持成员函数模板的trick

    罗朝辉 (http://www.cnblogs.com/kesalin/)

    本文遵循“署名-非商业用途-保持一致”创作公用协议
     
    gcc 4.7.3 不支持成员函数模板特化。如下代码:
     
    #ifndef __MEMFUNTEMPLATE_H__
    #define __MEMFUNTEMPLATE_H__
    
    #include <stdio.h>
    
    class Base {};
    class Derived : public Base {};
    
    struct Functor {
        template <typename T> void function() {
            printf(" Primary template....
    ");
        }
    
        template<>
        void function<int>(){
            printf(" Specialization for int....
    ");
        }
    
        template<> void function<Base *>() {
            printf(" Specialization for Base *....
    ");
        }
    };
    
    class Tester {
    public:
        static void DoTest()
        {
            Functor functor;
            functor.function<char>();
            functor.function<int>();
            functor.function<Base *>();
            functor.function<Derived *>();
        }
    };
    
    #endif // __MEMFUNTEMPLATE_H__

    在 VS2010 中编译运行是没有问题的,但在 gcc 4.7.3下,编译都通不过:

    ../src/MemFunTemplate.h:21:14: error: explicit specialization in non-namespace scope ‘struct Functor’
    ../src/MemFunTemplate.h:22:24: error: template-id ‘function<int>’ in declaration of primary template
    ../src/MemFunTemplate.h:26:14: error: explicit specialization in non-namespace scope ‘struct Functor’
    ../src/MemFunTemplate.h:26:38: error: template-id ‘function<Base*>’ in declaration of primary template
    ../src/MemFunTemplate.h:26:21: error: ‘void Functor::function()’ cannot be overloaded
    ../src/MemFunTemplate.h:22:10: error: with ‘void Functor::function()’
    ../src/MemFunTemplate.cpp: In function ‘int main()’:
    ../src/MemFunTemplate.cpp:17:2: error: ‘DoTest’ is not a member of ‘Functor’
    

    为了达到近似成员函数模板特化的效果,可以利用成员函数主模板以及重载函数来实现:

    /*
     * MemFunTemplate.h
     *
     *  Created on: Jul 12, 2013
     *      Author: http://blog.csdn.net/kesalin/
     */
    
    #ifndef MEMFUNTEMPLATE_H_
    #define MEMFUNTEMPLATE_H_
    
    #include <stdio.h>
    
    template<typename T>
    struct DummyIdentity {
        typedef T type;
    };
    
    class Base {};
    class Derived : public Base {};
    
    struct Functor {
        template <typename T> void function() {
            function(DummyIdentity<T>());
        }
    
    private:
    
        template <typename T>
        void function(DummyIdentity<T>) {
            printf(" Primary template DummyIdentity<T>....
    ");
        }
    
        void function(DummyIdentity<int>) {
            printf(" overload function for DummyIdentity<int>....
    ");
        }
    
        void function(DummyIdentity<Base *>) {
            printf(" overload function for DummyIdentity<Base *>....
    ");
        }
    };
    
    class Tester {
    public:
        static void DoTest()
        {
            Functor functor;
            functor.function<char>();
            functor.function<int>();
            functor.function<Base *>();
            functor.function<Derived *>();
        }
    };
    
    #endif /* MEMFUNTEMPLATE_H_ */

    调用 DoTest() 运行结果如下:

     Primary template DummyIdentity<T>....
     overload function for DummyIdentity<int>....
     overload function for DummyIdentity<Base *>....
     Primary template DummyIdentity<T>....

    注意:

    VS2010 版本的代码,模板形参为 T,在实例化不会进行隐式类型转换。即用 Derived * 当作实参调用的是主模板,而不是 Base * 特化版本

    而在 gcc  下,模板形参虽然也为T,但影响重载决议的 function 参数为:DummyIdentity<T>,用不同的实际参数实例化该模板,得到的是一堆重载函数。因此用 Derived * 当作实参时,调用的函数自然就是实例化的 void function(DummyIdentity<T>)了。

     
  • 相关阅读:
    web开发之mysql优化总结
    使用webpack构建属于你自己的npm包
    jwt在node中的应用与实践
    zookeeper启动失败解决办法(3.5.7)
    oracle表分区详解
    oracle job
    ORACLE恢复误删的表数据
    go mod使用 踏雪扬尘
    sparkcore 学习 踏雪扬尘
    GO语言基本知识 踏雪扬尘
  • 原文地址:https://www.cnblogs.com/kesalin/p/member_funtion_template.html
Copyright © 2011-2022 走看看