Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> специализация шаблона для списка типов 
:(
    Опции темы
Alek86
Дата 18.2.2008, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



есть шаблон (ну, к примеру, функции)

Код

template<class T>
void func (const T& t) {/*realization 1*/}


и нужно сделать 2 специализации (для int и для char)

Код

template<>
void func<int> (const T& t) {/*realization 2*/}

template<class T>
void func<char> (const T& t) {/*realization 2*/}


но тут оказалось, что специализации абсолютно идентичны (потому обе и называются realization 2). Есть ли какой хитрый механизм, который позволяет в этом случае избавиться от копипаста?


--------------------
user posted image    user posted image
PM MAIL   Вверх
Earnest
Дата 18.2.2008, 18:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Реализуй в не-темплэйтной функции и вызови ее из обеих реализаций.


--------------------
...
PM   Вверх
Alek86
Дата 18.2.2008, 18:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



наверное, условие не то. ща сподправим-с:
Код

template<class T>
bool equal (const T& t1, const T& t2) {
  return !(t1 < t2 || t1 < t2);
}

template<>
bool equal<int> (const int& i1, const int& i2) {
  return t1 == t2;
}

template<class T>
bool equal<char> (const char& c1, const char& c2) {
  return t1 == t2;
}

как в таком случае поступить?
(желательно пообщей рецепт, а не только для этого случая подходящий)


--------------------
user posted image    user posted image
PM MAIL   Вверх
Earnest
Дата 18.2.2008, 18:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



В данном случае проще копировать - было бы о чем говорить.
Если код заметно длиннее, то так:
Код

template <class T> bool simple_equal (const T& lhs, const T& rhs)
{
   return lhs == rhs;
}

template<>
bool equal<int> (const int& i1, const int& i2) 
{
   return simple_equal<int>(i1, i2);
}




--------------------
...
PM   Вверх
Alek86
Дата 18.2.2008, 19:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



да, наверное надо было сразу общный вопрос

а в случае с шаблонными классами?


--------------------
user posted image    user posted image
PM MAIL   Вверх
maxim1000
Дата 18.2.2008, 19:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



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

P.S.
конечно же, можно обобщить на несколько списков типов с соответствующими реализациями + одну для всех остальных типов


--------------------
qqq
PM WWW   Вверх
Alek86
Дата 18.2.2008, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



я примерно то и думал... думал, есть готовое

есть же шаблоны, что говорят, является ли тип наследником другого. с этим можно многое совершить, имхо )


--------------------
user posted image    user posted image
PM MAIL   Вверх
maxim1000
Дата 18.2.2008, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



Цитата(Alek86 @  18.2.2008,  19:55 Найти цитируемый пост)
есть же шаблоны, что говорят, является ли тип наследником другого. с этим можно многое совершить, имхо ) 

кстати, с наследованием тоже можно поиграться:

Код

struct A
{
  void func() {/*реализация1*/}
};
struct B
{
  void func() {/*реализация2*/}
};

template<typename T> struct qqq:public A {};
template<> struct qqq<int>:public B {};
template<> struct qqq<char>:public B {};
и т.д.

template<typename T>void func()
{
  qqq<T>().func();
}


smile

Это сообщение отредактировал(а) maxim1000 - 18.2.2008, 22:18


--------------------
qqq
PM WWW   Вверх
Alek86
Дата 19.2.2008, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



нельзя
если куча нужных конструкторов в A и B


--------------------
user posted image    user posted image
PM MAIL   Вверх
_stranger_
Дата 19.2.2008, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 52
Регистрация: 3.10.2006
Где: город-герой Киев

Репутация: 2
Всего: 2



Цитата(Alek86 @  18.2.2008,  18:28 Найти цитируемый пост)
есть шаблон (ну, к примеру, функции)

и нужно сделать 2 специализации (для int и для char)


кстати есть мнение что специализировать шаблон функции не есть гуд... вместо этого необходимо использовать перегрузку шаблона функции... аргументируется это тем что специализации шаблона функции никогда не учавствуют в перегрузке... 

PM MAIL   Вверх
Alek86
Дата 19.2.2008, 12:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



спасибо за информацию - но вопрос не о том smile


--------------------
user posted image    user posted image
PM MAIL   Вверх
maxim1000
Дата 19.2.2008, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



Цитата(Alek86 @  19.2.2008,  11:53 Найти цитируемый пост)
если куча нужных конструкторов в A и B

в смысле?
классы пустые, оптимизатор наверняка выкинет вообще всё, что можно


--------------------
qqq
PM WWW   Вверх
Alek86
Дата 19.2.2008, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



а, тьфу не так код прочел...
это еще один вариант перегрузки функций?

если да, то что насчет перегрузки классов? тут наследование не пройдет


--------------------
user posted image    user posted image
PM MAIL   Вверх
maxim1000
Дата 19.2.2008, 17:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



Цитата(Alek86 @  19.2.2008,  16:14 Найти цитируемый пост)
это еще один вариант перегрузки функций?

ну можно и так сказать


Цитата(Alek86 @  19.2.2008,  16:14 Найти цитируемый пост)
если да, то что насчет перегрузки классов? тут наследование не пройдет

в смысле выбор класса в зависимости от наличия/отсутствия в списке?

можно вместо объявления func делать typedef:
Код

struct A
{
  typedef ClassA type;
};
struct B
{
  typedef ClassB type;
};
template<typename T> struct qqq:public A {};
template<> struct qqq<int>:public B {};
template<> struct qqq<char>:public B {};
и т.д.
...
template<typename T>void anotherFunc()
{
  qqq<T>::type x;
  x.Work();
}



--------------------
qqq
PM WWW   Вверх
Alek86
Дата 19.2.2008, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



блин, хреновасто я вопрос этот задал...

думал, что можно перегружать для классов классов (гы-гы), подходящих под какое-то опреленное условие

примеры условий - тип класса находится в определенном списке типов, класс является наследником другого, у класса есть вирт деструктор (то есть от него можно безбоязненно наследоваться) и т.п.


то есть примерно то, что ты, maxim1000, в послежднем посте написал, только более автоматизированно



ЗЫ. справедливости ради нужно сказать, что и до того я чето не допетрил :(


--------------------
user posted image    user posted image
PM MAIL   Вверх
Alek86
Дата 20.2.2008, 10:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



не без помощи одолел проблему:

Код

enum TypeIs {Vacuous, InMultitude1, InMultitude2};

template <class T>
struct Condition {
  enum {
    Value =
    Condition1<T>::Right ? InMultitude1 : // sizeof(T) == 1
    Condition2<T>::Right ? InMultitude2 : // sizeof(T) == 2
    Vacuous
    };
};

template <class T>
struct Condition1 {
  enum {
    Right =
    (sizeof(T) == 1) ? true : false
  };
};

template <class T>
struct Condition2 {
  enum {
    Right =
    (sizeof(T) == 2) ? true : false
    };
};

template <class T, TypeIs = static_cast<TypeIs>(Condition<T>::Value)>
struct MainClass {
  enum {Value = 0};
};

template <class T>
struct MainClass<T, InMultitude1> {
  enum {Value = 10};
};

template <class T>
struct MainClass<T, InMultitude2> {
  enum {Value = 20};
};
1.
int main () {
  std::cout << "char  " << MainClass<char>::Value  << std::endl; // sizeof(T) == 1 => 10
  std::cout << "int   " << MainClass<int>::Value   << std::endl; // sizeof(T) == 4 => 0
  std::cout << "short " << MainClass<short>::Value << std::endl; // sizeof(T) == 2 => 20
};


на MVS 2005 пашет и правильно
осталась пара вопросов

1. это по стандарту такое поведение, что если в
Код
template <class T, TypeIs = static_cast<TypeIs>(Condition<T>::Value)>

Код
static_cast<TypeIs>(Condition<T>::Value)

возвращает InMultitude1, то даже несмотря на то, что компилятор уже начал, фактически, подставлять главный шаблон, он все равно еще раз пробегает по всем специализациям и находит
Код
template <class T>
struct MainClass<T, InMultitude1> {
  enum {Value = 10};
};

?

2. как-то можно избавиться в этом случае от статик каста в
Код
static_cast<TypeIs>(Condition<T>::Value)

?


--------------------
user posted image    user posted image
PM MAIL   Вверх
_stranger_
Дата 20.2.2008, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 52
Регистрация: 3.10.2006
Где: город-герой Киев

Репутация: 2
Всего: 2



Мне кажется проблемма не до конца решена, вот например посмотри подставляем long и double
Код

  std::cout << "char  " << MainClass<char>::Value  << std::endl; // sizeof(T) == 1 => 10
  std::cout << "int   " << MainClass<int>::Value   << std::endl; // sizeof(T) == 4 => 0
  std::cout << "short " << MainClass<short>::Value << std::endl; // sizeof(T) == 2 => 20
  std::cout << "long  " << MainClass<long>::Value  << std::endl;  //sizeof(T) == 4 => 0 вот тут тип не определен
  std::cout << "double  " << MainClass<double>::Value  << std::endl; //sizeof(T) == 8 => 0 и тут



я вот так пытался решить эту проблему с помощью списков типов, но тоже проблема до конца не решена:
Код

class NullType{};

template <class T,class U>
struct TypeList
{
    typedef T Head;
    typedef U Tail;
};

#define TYPELIST_1(T1)  TypeList<T1,NullType>
#define TYPELIST_2(T1,T2) TypeList<T1,TYPELIST_1(T2)>

template <class T>
void func(T& ptr)
{
    std::cout << "func" << std::endl;
}

template <class T>
void funcIntChar(T& ptr)
{
    std::cout << "funcIntChar" << std::endl;
}

template <class TList,class T>
class Wrapper
{
    typedef typename TList::Head Head;
    typedef typename TList::Tail Tail;
public:
    enum {value = (sizeof(Head) == sizeof(T))? 1:Wrapper<Tail,T>::value};
    void operator()(T temp)
    {
        if(value)
        {
            funcIntChar(temp);
        }
        else
        {
            func(temp);
        }
    }
};

template <class T>
class Wrapper<NullType,T>
{
public:
    enum {value = 0};
};
int main ()
{
    double x = 5.5;
    Wrapper<TYPELIST_2(int,char),double> Temp; //применение
    Temp(x);
}



Это сообщение отредактировал(а) _stranger_ - 20.2.2008, 11:36
PM MAIL   Вверх
Alek86
Дата 20.2.2008, 11:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

Репутация: 21
Всего: 25



Код

std::cout << "char  " << MainClass<char>::Value  << std::endl; // sizeof(T) == 1 => 10
  std::cout << "int   " << MainClass<int>::Value   << std::endl; // sizeof(T) == 4 => 0
  std::cout << "short " << MainClass<short>::Value << std::endl; // sizeof(T) == 2 => 20
  std::cout << "long  " << MainClass<long>::Value  << std::endl;  //sizeof(T) == 4 => 0 вот тут тип определен
  std::cout << "double  " << MainClass<double>::Value  << std::endl; //sizeof(T) == 8 => 0 и тут


у меня выводится все, как я ожидал
для sizeof(T) == 1          выводится 10
для sizeof(T) == 2          выводится 20
для остальных случаев выводится  0

sizeof тут чисто для проверки работы. вместо
Код
(sizeof(T) == N)
 можно подставить любое условие времени компиляции (и принадлежность к списку типов тоже)


--------------------
user posted image    user posted image
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1255 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.