template <class frac_type>
void tvertex2d <double>:: copy_data (tvertex2d <frac_type>& copy)
{
tarray <tvector2d <frac_type >,3,3 >:: copy_data(copy);
};
template <class frac_type>
void tvertex2d <tfixed32>:: copy_data (tvertex2d <frac_type>& copy)
{
tarray <tvector2d <frac_type >,3,3 >:: copy_data(copy);
};
Шаблонные классы
Причем таким образом, чтоб нужная версия выбиралась в зависимости от переданного в шаблон параметра.
На Watcom C/C++ следующий код работал:
Код:
А когда стал делать нечто подобное на vcpp, получил грабли:
Код:
template <class T, tSmartPtrBase::ptr_kind kind>
void tSmartPtr<T, tSmartPtrBase::object>::operator delete(void *buf)
{::delete (T*)buf;};
template <class T, tSmartPtrBase::ptr_kind kind>
void tSmartPtr<T, tSmartPtrBase::com>::operator delete(void *buf)
{((T*)buf)->Release();};
void tSmartPtr<T, tSmartPtrBase::object>::operator delete(void *buf)
{::delete (T*)buf;};
template <class T, tSmartPtrBase::ptr_kind kind>
void tSmartPtr<T, tSmartPtrBase::com>::operator delete(void *buf)
{((T*)buf)->Release();};
Вопрос: как переделать второй кусок кода, что бы грабли исчезли?
P.S.:
Шаблонный параметр здесь может принимать только два значения.
Код:
struct tSmartPtrBase
{
enum ptr_kind
{
object,
com
};
};
//Основной шаблон
template <class T, tSmartPtrBase::ptr_kind kind>
struct tSmartPtr
{
//
};
//Шаблон, специализированный по kind
template <class T>
struct tSmartPtr<T, tSmartPtrBase::object>
{
void operator delete(void *buf);
};
//Шаблон, специализированный по kind
template <class T>
struct tSmartPtr<T, tSmartPtrBase::com>
{
void operator delete(void *buf);
};
template <class T>
void tSmartPtr<T, tSmartPtrBase::object>::operator delete(void *buf)
{
::delete (T*)buf;
}
template <class T>
void tSmartPtr<T, tSmartPtrBase::com>::operator delete(void *buf)
{
((T*)buf)->Release();
};
{
enum ptr_kind
{
object,
com
};
};
//Основной шаблон
template <class T, tSmartPtrBase::ptr_kind kind>
struct tSmartPtr
{
//
};
//Шаблон, специализированный по kind
template <class T>
struct tSmartPtr<T, tSmartPtrBase::object>
{
void operator delete(void *buf);
};
//Шаблон, специализированный по kind
template <class T>
struct tSmartPtr<T, tSmartPtrBase::com>
{
void operator delete(void *buf);
};
template <class T>
void tSmartPtr<T, tSmartPtrBase::object>::operator delete(void *buf)
{
::delete (T*)buf;
}
template <class T>
void tSmartPtr<T, tSmartPtrBase::com>::operator delete(void *buf)
{
((T*)buf)->Release();
};
Цитата: k3Eahn
Насколько я понял, ты пытаешься частично специализировать метод. Если мне не изменяет память, так делать нельзя. Но зато частичной специализации можно подвергнуть класс.
Идея хорошая. Все так и сделал. Только теперь компилер ругается на отсутствие подходящего конструктора, когда я пытаюсь проинициализировать объект указателем.
Код:
int WINAPI WinMain(
HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow
)
{
int *p0 = new int(4);
int *p1 = new int(9);
//int *p2 = new int(15);
tSmartPtr<int, tSmartPtrBase::obj> a(p0); // строка (28)
tSmartPtr<int, tSmartPtrBase::obj> b(p0);
tSmartPtr<int, tSmartPtrBase::obj> c(p1);
//a.clone();
a = b;
MessageBox(NULL, "Ok!", "note", MB_OK);
return 0;
};
class tSmartPtrBase
{
protected:
static __int64 nSPCnt;
static std::map<void *, __int64, std::less<void *> > *pRefCnt;
void IncRefCnt(void *ptr);
bool DecRefCnt(void *ptr);
public:
tSmartPtrBase();
virtual ~tSmartPtrBase();
enum ptr_kind {obj, com};
};
template <class T, tSmartPtrBase::ptr_kind kind>
class tSmartPtr: public tSmartPtrBase
{
T *ptr;
public:
tSmartPtr(): ptr(NULL) {};
tSmartPtr(const tSmartPtr<T, kind>& pSmartPtr);
tSmartPtr(T *pNewPtr);
~tSmartPtr();
T *get(void) {return ptr;};
void clone(void);
tSmartPtr operator=(tSmartPtr pSmartPtr);
tSmartPtr operator=(T *pNewPtr);
T *operator ->();
T &operator *();
};
template <class T>
class tSmartPtr<T, tSmartPtrBase::obj>: public tSmartPtrBase
{
void operator delete(void *buf);
};
template <class T>
class tSmartPtr<T, tSmartPtrBase::com>: public tSmartPtrBase
{
void operator delete(void *buf);
};
HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow
)
{
int *p0 = new int(4);
int *p1 = new int(9);
//int *p2 = new int(15);
tSmartPtr<int, tSmartPtrBase::obj> a(p0); // строка (28)
tSmartPtr<int, tSmartPtrBase::obj> b(p0);
tSmartPtr<int, tSmartPtrBase::obj> c(p1);
//a.clone();
a = b;
MessageBox(NULL, "Ok!", "note", MB_OK);
return 0;
};
class tSmartPtrBase
{
protected:
static __int64 nSPCnt;
static std::map<void *, __int64, std::less<void *> > *pRefCnt;
void IncRefCnt(void *ptr);
bool DecRefCnt(void *ptr);
public:
tSmartPtrBase();
virtual ~tSmartPtrBase();
enum ptr_kind {obj, com};
};
template <class T, tSmartPtrBase::ptr_kind kind>
class tSmartPtr: public tSmartPtrBase
{
T *ptr;
public:
tSmartPtr(): ptr(NULL) {};
tSmartPtr(const tSmartPtr<T, kind>& pSmartPtr);
tSmartPtr(T *pNewPtr);
~tSmartPtr();
T *get(void) {return ptr;};
void clone(void);
tSmartPtr operator=(tSmartPtr pSmartPtr);
tSmartPtr operator=(T *pNewPtr);
T *operator ->();
T &operator *();
};
template <class T>
class tSmartPtr<T, tSmartPtrBase::obj>: public tSmartPtrBase
{
void operator delete(void *buf);
};
template <class T>
class tSmartPtr<T, tSmartPtrBase::com>: public tSmartPtrBase
{
void operator delete(void *buf);
};
Пишет:
(28) : error C2664: 'tSmartPtr<T,kind>::tSmartPtr(const tSmartPtr<T,kind> &)' : cannot convert parameter 1 from 'int *' to 'const tSmartPtr<T,kind> &'
Код:
class tSmartPtrBase
{
protected:
static __int64 nSPCnt;
static std::map<void *, __int64, std::less<void *> > *pRefCnt;
void IncRefCnt(void *ptr);
bool DecRefCnt(void *ptr);
public:
tSmartPtrBase();
virtual ~tSmartPtrBase();
template <class Tptr>
struct obj
{void operator delete(void *buf);}; // Tptr используется для
// приведения типа в теле
// оператора
template <class Tptr>
struct com
{void operator delete(void *buf);};
};
template <class T, class kind>
class tSmartPtr: public tSmartPtrBase
{
T *ptr;
public:
tSmartPtr(): ptr(NULL) {};
tSmartPtr(const tSmartPtr<T, kind>& pSmartPtr);
tSmartPtr(T *pNewPtr);
~tSmartPtr();
T *get(void) {return ptr;};
void clone(void);
tSmartPtr operator=(tSmartPtr pSmartPtr);
tSmartPtr operator=(T *pNewPtr);
T *operator ->();
T &operator *();
};
{
protected:
static __int64 nSPCnt;
static std::map<void *, __int64, std::less<void *> > *pRefCnt;
void IncRefCnt(void *ptr);
bool DecRefCnt(void *ptr);
public:
tSmartPtrBase();
virtual ~tSmartPtrBase();
template <class Tptr>
struct obj
{void operator delete(void *buf);}; // Tptr используется для
// приведения типа в теле
// оператора
template <class Tptr>
struct com
{void operator delete(void *buf);};
};
template <class T, class kind>
class tSmartPtr: public tSmartPtrBase
{
T *ptr;
public:
tSmartPtr(): ptr(NULL) {};
tSmartPtr(const tSmartPtr<T, kind>& pSmartPtr);
tSmartPtr(T *pNewPtr);
~tSmartPtr();
T *get(void) {return ptr;};
void clone(void);
tSmartPtr operator=(tSmartPtr pSmartPtr);
tSmartPtr operator=(T *pNewPtr);
T *operator ->();
T &operator *();
};
По поводу умных указателей советую почитать Александреску. В частности стоит уделить внимание использованию стратегий (владения, хранения).