一道C++模板题

来源:互联网 发布:淘宝买家投诉三无产品 编辑:程序博客网 时间:2024/06/18 11:17
 昨天在TRW2000的作者刘涛涛的blog上看到了一道c++模板题,一时兴起,就作了起来。

题目如下:

#include <stdio.h>
#include <new>

typedef unsigned char BYTE;
typedef unsigned char * PBYTE;

class LZF
{
public:
     int num;
     LZF(): num(133)
     {
     }
};

template <class T>
class Auto1
{
     T* m_p;
public:
     T* Allocate(void)
     {
         PBYTE pnew = new BYTE[sizeof(T) + 10];
         T* p = (T*)pnew;
         if (p != NULL)
         {
             ::new( (void*)p ) T;      // 调用Class的构造函数
         }
         m_p = p;
         return p;
     }
};

template <class T>
class Auto2
{
     T m_p;
public:
     T Allocate(void)
     {
         PBYTE pnew = new BYTE[sizeof(*m_p) + 10];
         T p = (T)pnew;
         if (p != NULL)
         {
            ::new( (void*)p ) *T;//这里编译出错。如何调用Class的构造函数?
         }
         m_p = p;
         return p;
     }

};

void test1()
{
     Auto1<LZF> a;
     int ret = a.Allocate()->num;
     if (ret == 133)
     {
         printf("good %d/n",ret);        
     }
     else
     {
         printf("error");
     }
}
void test2()
{
     Auto2<LZF*> a;
     int ret = a.Allocate()->num;
     if (ret == 133)
     {
         printf("good %d/n",ret);        
     }
     else
     {
         printf("error");
     }
}

int main( void )
{    
     test1();
     test2();
   return 0;
}

调用C++编译器编译这段代码,会在红色加黑的那一行报出编译期错误,因为编译器无法根据指针类型确定调用

哪个类的构造函数。


想了一下,这个问题应该可以用c++里的traits技术来解决,下面给出我的解决方案:

#include <stdio.h>
#include <new>
typedef unsigned char BYTE;
typedef unsigned char * PBYTE;
using namespace std;

class LZF
{
public:
    int num;
    LZF(): num(133)
    {
    }
};

template <class T>
class Auto1
{
    T* m_p;
public:
    T* Allocate(void)
    {
        PBYTE pnew = new BYTE[sizeof(T) + 10];
        T* p = (T*)pnew;
        if (p != NULL)
        {
            ::new( (void*)p ) T;     // 调用Class的构造函数
        }
        m_p = p;
        return p;
    }
};

// 泛化的traits类,用于提取模块实例化类型的类型信息
template<class T>
class typeTraits {
    public:
        typedef T val_type;
};

// 偏特化的traits类,用于专门针对指针类型来提取其相应的实体类类型信息
template<class T>
class typeTraits<T*>{
    public:
        typedef T val_type;
};


template <class T>
class Auto2
{
    T m_p;
public:
    T Allocate(void)
    {
        PBYTE pnew = new BYTE[sizeof(*m_p) + 10];
        T p = (T)pnew;
        if (p != NULL)
        {
            // ::new( (void*)p ) *T;//这里编译出错。如何调用Class的构造函数?
            ::new( (void*)p ) typename typeTraits<T>::val_type;//通过traits来提取出指针类型所对应的实体类的类型信息
        }
        m_p = p;
        return p;
    }

};

void test1()
{
    Auto1<LZF> a;
    int ret = a.Allocate()->num;
    if (ret == 133)
    {
        printf("good %d/n",ret);
    }
    else
    {
        printf("error");
    }
}
void test2()
{
    Auto2<LZF*> a;
    int ret = a.Allocate()->num;
    if (ret == 133)
    {
        printf("good %d/n",ret);
    }
    else
    {
        printf("error");
    }
}

int main( void )
{
    test1();
    test2();

    return 0;
}


用g++编译测试了 下我的方案,成功通过,打印如下信息:

good 133
good 133

理解这个解决方案的关键是c++里对模板偏特化的支持,以及STL里traits技术的机理。这里

暂时就不再多述了。
原创粉丝点击