Чего-то подзабыл плюсы. Специализация
От: gwg-605 Россия  
Дата: 25.08.10 07:46
Оценка:
Есть темплейт:

template <class _T>
class TName {
protected:
    _T member ;

public:
    _T get() { return( member ) ; }
    void Set( _T v ) { member = v ; }

    здесь еще 100 тысяч методов :)
} ;



надо для определенного типа изменить только реализацию методов get и set, оставив дефолтную для всех остальных методов. Думал что можно это провернуть через специализацию, но не выходит каменный цветок или я глобально не прав?

ЗЫ. Поискал по инету, описания не дают ответ на мой вопрос, а примеры состоят либо из одного метода, либо все методы и члены класса специализируются.
Re: Чего-то подзабыл плюсы. Специализация
От: pavel.yurchenko Украина  
Дата: 25.08.10 07:51
Оценка: 2 (1)
Здравствуйте, gwg-605, Вы писали:

G6>Есть темплейт:


G6>
G6>template <class _T>
G6>class TName {
G6>protected:
G6>    _T member ;

G6>public:
G6>    _T get() { return( member ) ; }
G6>    void Set( _T v ) { member = v ; }

G6>    здесь еще 100 тысяч методов :)
G6>} ;
G6>



G6>надо для определенного типа изменить только реализацию методов get и set, оставив дефолтную для всех остальных методов. Думал что можно это провернуть через специализацию, но не выходит каменный цветок или я глобально не прав?


G6>ЗЫ. Поискал по инету, описания не дают ответ на мой вопрос, а примеры состоят либо из одного метода, либо все методы и члены класса специализируются.


Может сами метотды get и set сделать шаблонными и сделать им специализации?
Re: Чего-то подзабыл плюсы. Специализация
От: Erop Россия  
Дата: 25.08.10 07:52
Оценка: 2 (1)
Здравствуйте, gwg-605, Вы писали:

G6>
G6>template <class _T>
G6>class TName {
G6>protected:
G6>    _T member ;

G6>public:
G6>    _T get() { return( member ) ; }
G6>    void Set( _T v ) { member = v ; }

G6>    здесь еще 100 тысяч методов :)
G6>} ;
G6>



G6>надо для определенного типа изменить только реализацию методов get и set, оставив дефолтную для всех остальных методов. Думал что можно это провернуть через специализацию, но не выходит каменный цветок или я глобально не прав?


template<> ТотСамыйТип TName<ТотСамыйТип>::get()
{
    //  Тут реализация
}
template<> void TName<ТотСамыйТип>::Set( ТотСамыйТип v )
{
    //  Тут реализация
}
Правда поля у класса будут те же. Поментяь сможешь только тела самих методов.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Чего-то подзабыл плюсы. Специализация
От: gwg-605 Россия  
Дата: 25.08.10 07:52
Оценка:
Здравствуйте, pavel.yurchenko, Вы писали:

PY>Может сами метотды get и set сделать шаблонными и сделать им специализации?

Спасибо! Направление понял!
Re[2]: Чего-то подзабыл плюсы. Специализация
От: Erop Россия  
Дата: 25.08.10 07:55
Оценка:
Здравствуйте, pavel.yurchenko, Вы писали:

PY>Может сами метотды get и set сделать шаблонными и сделать им специализации?


Тогда уж проще написать прямо в шаблоне методы для того самого типа, но так, чтобы если параметр шаблона не тот, методы не скомпилировались...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Чего-то подзабыл плюсы. Специализация
От: Кодт Россия  
Дата: 25.08.10 08:13
Оценка: 5 (3) +2
#Имя: FAQ.cpp.specialization
Здравствуйте, gwg-605, Вы писали:

G6>надо для определенного типа изменить только реализацию методов get и set, оставив дефолтную для всех остальных методов. Думал что можно это провернуть через специализацию, но не выходит каменный цветок или я глобально не прав?


Способ номер раз: ответ на твой вопрос
template<class T> class X
{
  T get() {...}
  void set(T) {...}
  T foo();
  void bar() {...}
};

// специализация
template<> inline int X<int>::get() {!!!}
template<> char X<char>::get();

// инстанцирование шаблона (объявление)
template int X<int>::foo();
template char X<char>::foo();

// где-то в .cpp
template<class T> T X<T>::foo() {...}

template<> char X<char>::get() {???}


Способ номер два:
template<class T> class getset // и специализируй его сколько влезет
{
  T data;
public:
  T get() {...}
  void set(T) {...}
};

template<class T> class X : public getset<T>
{
  .......
};

Этот подход и идеологически чище, и даёт больше возможностей, поскольку частичная специализация функций невозможна, а с классами творят чудеса.

Способ номер три:
template<class T> class X;

// семейство внешних функций
template<class T> T getx(X<T>&);
template<class T> void setx(X<T>&);

Удобен тем, что можно вместо специализации шаблонов использовать перегрузку и тоже творить чудеса.
Но надо быть очень аккуратным с порядком объявления того и другого — там есть ряд неочевидных граблей, связанных с областями видимости.
Против этих граблей можно побороться, запихав внешние функции в шаблон класса, а дальше см. номер два и номер три рекурсивно
http://files.rsdn.org/4783/catsmiley.gif Перекуём баги на фичи!
Re[2]: Чего-то подзабыл плюсы. Специализация
От: pavel.yurchenko Украина  
Дата: 25.08.10 08:23
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Способ номер два:

К>
К>template<class T> class getset // и специализируй его сколько влезет
К>{
К>  T data;
К>public:
К>  T get() {...}
К>  void set(T) {...}
К>};

К>template<class T> class X : public getset<T>
К>{
К>  .......
К>};
К>

К>Этот подход и идеологически чище, и даёт больше возможностей, поскольку частичная специализация функций невозможна, а с классами творят чудеса.

второй способ очень красивый. Не удержался и сам попробовал:


template<class T> class getset // и специализируй его сколько влезет
{
    T data;
public:
    T get() { return data; }
    void set(T value) { data = value; }
};

template<> class getset<int> // и специализируй его сколько влезет
{
    int data;
public:
    int get() { return -1; }
    void set( int data ) { data = -2; }
};


template<class T> class X : public getset<T>
{
};


int main( int argc, char * argv[] )
{
    std::cout << "test" << std::endl;
    
    typedef float floatType;
    typedef int intType;
    
    X<floatType> fName;
    fName.set( 10.5 );
    std::cout << "float instance value = " << fName.get() << std::endl;
    
    X<intType> iName;
    iName.set( 9 );
    std::cout << "int instnce value = " << iName.get() << std::endl;
    
    return 0;
}


На выводе:
testfloat instance value = 10.5
int instnce value = -1

То есть работает замечательно.

+1
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.