Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Шаблонные классы

991
02 марта 2007 года
Zenhipster
157 / / 14.01.2005
Вобщем есть задача реализовать две версии метода шаблонного класса.
Причем таким образом, чтоб нужная версия выбиралась в зависимости от переданного в шаблон параметра.
На Watcom C/C++ следующий код работал:
Код:
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);

};


А когда стал делать нечто подобное на 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();};


Вопрос: как переделать второй кусок кода, что бы грабли исчезли?

P.S.:
Шаблонный параметр здесь может принимать только два значения.
1.8K
02 марта 2007 года
k3Eahn
365 / / 19.12.2005
Насколько я понял, ты пытаешься частично специализировать метод. Если мне не изменяет память, так делать нельзя. Но зато частичной специализации можно подвергнуть класс. Т.е. сделать что-то вроде этого:
Код:
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();
};
991
02 марта 2007 года
Zenhipster
157 / / 14.01.2005
Цитата: 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);
};


Пишет:
(28) : error C2664: 'tSmartPtr<T,kind>::tSmartPtr(const tSmartPtr<T,kind> &)' : cannot convert parameter 1 from 'int *' to 'const tSmartPtr<T,kind> &'
991
02 марта 2007 года
Zenhipster
157 / / 14.01.2005
Нашел альтернативный вариант. Было принято решение передавать через шаблон класс - деаллокатор:

Код:
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 *();
};
1.8K
02 марта 2007 года
k3Eahn
365 / / 19.12.2005
По поводу умных указателей советую почитать Александреску. В частности стоит уделить внимание использованию стратегий (владения, хранения).
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог