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

    添加时间:2013-7-12 点击量:

    让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....\n);
    }

    template
    <>
    void function<int>(){
    printf(
    Specialization for int....\n);
    }

    template
    <> void function<Base >() {
    printf(
    Specialization for Base ....\n);
    }
    };

    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>....\n);
    }

    void function(DummyIdentity<int>) {
    printf(
    overload function for DummyIdentity<int>....\n);
    }

    void function(DummyIdentity<Base >) {
    printf(
    overload function for DummyIdentity<Base >....\n);
    }
    };

    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>)了。



     
    我们永远不要期待别人的拯救,只有自己才能升华自己。自己已准备好了多少容量,方能吸引对等的人与我们相遇,否则再美好的人出现、再动人的事情降临身边,我们也没有能量去理解与珍惜,终将擦肩而过。—— 姚谦《品味》
    分享到: