昨天在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技术的机理。这里
暂时就不再多述了。
题目如下:
#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技术的机理。这里
暂时就不再多述了。