Russian Qt Forum
Ноябрь 23, 2024, 19:13 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3] 4 5 6   Вниз
  Печать  
Автор Тема: Шаблоны.  (Прочитано 36774 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #30 : Март 25, 2012, 23:54 »

Поскольку в базовом классе CoordVec нет никакого вектора, то во-первых придётся использовать либо dynamic_cast, либо static_cast если известно к чему приводить..
И так вы не избавитесь от switch или ему подобных проверок и т.д. В этом плане этот вариант, конечно проигрывает..
Да и вызов виртуальных функций - тож дороговато( (а если учесть, что это чтение/запись)
Ну эти соображения очевидны. А подумать, толкнуть идейку? Или умеем только утешать PinkPink ?  Улыбающийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #31 : Март 26, 2012, 09:15 »

Цитировать
Ну эти соображения очевидны. А подумать, толкнуть идейку? Или умеем только утешать PinkPink ? 
Ну на мой взгляд, самое правильное решение это сделать класс CModel шаблонным.
Код
C++ (Qt)
template <class T>
class CModel {
   typedef T pointType;
   typedef std::vector<T> vectorType;
 
   vectorType *mCoord;
};
 
Это лучше и быстрее будет работать, нежели наследование, виртуальные функции и т.д.
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #32 : Март 26, 2012, 11:46 »

Да, есть ещё такая фишка, как определить принадлежность какого-либо объекта к конкретному классу/типу. Может будет где полезно:
Код
C++ (Qt)
template<class T>
struct tester
{
   static bool is_same(const T&) { return true; }
   template <class U>
   static bool is_same(const U&) { return false; }
};
 
Используется это так:
Код
C++ (Qt)
int i;
std::cout << tester<int>::is_same(i) << std::endl;
std::cout << tester<long>::is_same(i) << std::endl;
 
A *a = new A;
std::cout << tester<A>::is_same(*a) << std::endl;
std::cout << tester<B>::is_same(*a) << std::endl;
 
 
Вывод будет таким:
Код
Bash
true
false
 
true
false
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #33 : Март 26, 2012, 12:14 »

Ну на мой взгляд, самое правильное решение это сделать класс CModel шаблонным.
Минусы такого решения подробно описаны в посте #22
http://www.prog.org.ru/index.php?topic=21385.msg148020#msg148020

Да, есть ещё такая фишка, как определить принадлежность какого-либо объекта к конкретному классу/типу. Может будет где полезно:
С 3-мя базовыми классами уже 9 вариантов, с большим...

Рассмотрим такое
Код
C++ (Qt)
template <class T1, class T2>
void Append( T1 & dst. const T2 & src );
 
Здесь очевидно никаких проблем нет. Можем ли мы как-то выдернуть (как бы "привести") базовый класс к template когда нам нужно? Это звучит не очень грамотно, но Вы поняли идею.

Ну или хотя бы число приведений было = числу базовых классов. Потому что таких ф-ций как Append достаточно и "обильно свитчеваться" не хочется
« Последнее редактирование: Март 26, 2012, 12:15 от Igors » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #34 : Март 26, 2012, 12:30 »

Цитировать
Минусы такого решения подробно описаны в посте #22
А создавать базовые классы и определять туеву хучу виртуальных методов, это, конечно, достойная альтернатива))

Цитировать
Рассмотрим такое
Код
C++ (Qt)
template <class T1, class T2>
void Append( T1 & dst. const T2 & src );
 

Здесь очевидно никаких проблем нет. Можем ли мы как-то выдернуть (как бы "привести") базовый класс к template когда нам нужно? Это звучит не очень грамотно, но Вы поняли идею.
 
Не совсем понял..
Я бы написал специализацию этой функции..
Код
C++ (Qt)
template<>
void Append<vestor<PointD>, PointD>(vestor<PointD>& dst, const PointD &src);
 

Ну или что там под T1, T2 подразумевается..
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #35 : Март 26, 2012, 12:42 »

Идея написать свой базовый контейнер, имхо, пройгрышна.
Во-первых, по производительности.
Во-вторых, добавляется ещё много всякого кода (базовый класс, наследники, виртуальные функции)
В-третьих, страдает расширяемость и гибкость. Что если в будущем понадобится добавить ещё какой нить класс Точки? Всюду придётся переписывать всё.. Не гут(


 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #36 : Март 26, 2012, 13:05 »

А создавать базовые классы и определять туеву хучу виртуальных методов, это, конечно, достойная альтернатива))
Более чем. Даже если не существует хорошего решения для Append - я имею головную боль всего с одним классом, а в Вашем варианте - со всем приложением.

Не совсем понял..
Я бы написал специализацию этой функции..
Код
C++ (Qt)
template<>
void Append<vestor<PointD>, PointD>(vestor<PointD>& dst, const PointD &src);
 

А откуда я возьму Point3D (или др) если известен только базовый класс (который не template)?

Идея написать свой базовый контейнер, имхо, пройгрышна.
...
В-третьих, страдает расширяемость и гибкость. Что если в будущем понадобится добавить ещё какой нить класс Точки? Всюду придётся переписывать всё.. Не гут(
Зачем же мне всюду переписывать если классы верхнего уровня даже не знают о существовании разных форматов точек?  Улыбающийся
Код
C++ (Qt)
class CModel {
...
CoordVec * mCoord;
};
 

Во-первых, по производительности.
Во-вторых, добавляется ещё много всякого кода (базовый класс, наследники, виртуальные функции)
Ага, а вот и результат общения с PinkPink  Улыбающийся

[offtop]Конечно чтение книг развивает и.т.п. Но в то же время читающий "оказывается под влиянием". Ход мыслей сводится к подстановке/перебору стандартных решений (часто пошленьких), активность/инициатива подавляется. Если в книжке такого не находится, то это немедленно объявляется (позорным) велосипедом. Увы, это работает даже для тех людей у которых с креативом все нормально  Улыбающийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #37 : Март 26, 2012, 13:13 »

По поводу функции Append:
Её можно сделать так:
Код
C++ (Qt)
template <class Point>
void Append( vector<Point> & dst, const vector<Point> & src ) {...}
 
Если для конкретного типа Point (пусть для определённости PointF) реализация будет отлична от общей, то логично просто написать специализацию:
Код
C++ (Qt)
template <>
void Append<PointF>( vector<PointF> & dst, const vector<PointF> & src ) {...}
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #38 : Март 26, 2012, 13:29 »

У меня как-то была похожая задачка. Нужно было реализовать некий класс, который использовал контейнер, но важно было дать возможность пользователю самому выбирать тип контейнера (вектора). Это, например мог быть и std::vector, и valarray и std::array, и даже std::complex (как двумерный вектор). Через шаблоны получилось очень прикольно)

Могу привести код) 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #39 : Март 26, 2012, 13:38 »

Если для конкретного типа Point (пусть для определённости PointF) реализация будет отлична от общей, то логично просто написать специализацию:
С этим ясно, также для простоты предположим все базовые структуры могут присваиваться друг другу, это легко обеспечить. Но где мне взять тип? Давайте набросаем первый (пусть уродливый) вариант

Код
C++ (Qt)
void Append( CoordVec & dst, const CoordVec & src )
{
switch (dst.Format()) {
 case format_3doub:
   switch (src.Format()) {
    case format_3doub:
    {
      CoordVecT <Point3D> & srcT = (CoordVecT <Point3D> &) src;
      CoordVecT <Point3D> & dstT = (CoordVecT <Point3D> &) dst;
      dst.mData.insert(...);
      break;
    }
    ...
 .... // и.т.д
   }
 .... // и.т.д
}
 
}
 
Конечно это ужасно Улыбающийся Но при полном отсутствии лучшего на это можно пойти. Хорошо, как это можно сделать лучше - или хотя бы менее болезненно?

У меня как-то была похожая задачка. Нужно было реализовать некий класс, который использовал контейнер, но важно было дать возможность пользователю самому выбирать тип контейнера (вектора). Это, например мог быть и std::vector, и valarray и std::array, и даже std::complex (как двумерный вектор). Через шаблоны получилось очень прикольно)

Могу привести код) 
Идею поясните, а с кодом я разберусь
« Последнее редактирование: Март 26, 2012, 13:40 от Igors » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #40 : Март 26, 2012, 14:01 »

Цитировать
С этим ясно, также для простоты предположим все базовые структуры могут присваиваться друг другу, это легко обеспечить. Но где мне взять тип? Давайте набросаем первый (пусть уродливый) вариант
Тип шаблона легко определить. Например так:
Код
C++ (Qt)
enum PointType {TypePointD, TypePointF, TypePointX, TypeUnknown};
 
template <class T>
struct traits {
static PointType type() { return TypeUnknown; }
};
 
template<>
struct traits<PointF>
{
static PointType type() { return TypePointF; }
};
 
template<>
struct traits<PointD>
{
static PointType type() { return TypePointD; }
};
 
template<>
struct traits<PointX>
{
static PointType type() { return TypePointX; }
};
 

Теперь можно Ваш авариант функции Append написать через шаблоны:
Код
C++ (Qt)
template <class Point>
void Append(vector<Point>& dst, const vector<Point> & src)
{
   PointType pt = traits<Point>::type();
   switch (pt) {
   case TypePointF:  {...} break;
   case TypePointD:  {...} break;
   case TypePointX:  {...} break;
   default: {...}  
   }
}
 

Ну как то так это видится..
« Последнее редактирование: Март 26, 2012, 14:11 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #41 : Март 26, 2012, 14:14 »

Теперь можно Ваш авариант функции Append написать через шаблоны:
Код
C++ (Qt)
template <class Point>
void Append(vector<Point>& dst, const vector<Point> & src)
{
   PointType pt = traits<Point>::type();
   switch (pt) {
   case PointF:  {...} break;
   case PointD:  {...} break;
   case PointX:  {...} break;
   default: {...}  
   }
}
 

Ну как то так это видится..
Если бы я мог записать напр vector<Point>& dst - то тело ф-ции выписывается прекрасно без всяких switch. Но беда в том что аргументом(и) должен быть базовый класс который не template
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #42 : Март 26, 2012, 14:17 »

Цитировать
Если бы я мог записать напр vector<Point>& dst - то тело ф-ции выписывается прекрасно без всяких switch. Но беда в том что аргументом(и) должен быть базовый класс который не template
Ну так может и не стоит порождать базовый класс и его наследников, а сразу сделать через шаблоны?
Я просто не могу понять (несколько раз читал пост 22) чем же всё-таки вариант с шаблоном не устраивает? 
Я пока не вижу проблемы..
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #43 : Март 26, 2012, 14:40 »

Ну так может и не стоит порождать базовый класс и его наследников, а сразу сделать через шаблоны?
Я просто не могу понять (несколько раз читал пост 22) чем же всё-таки вариант с шаблоном не устраивает? 
Я пока не вижу проблемы..
Меня совершенно не устраивает что все (абсолютно все) что хоть как-то связано с таким контейнером сразу же само становится template и требует спецификации. Добавили такой контейнер к чему-то (напр как член класса) - извольте и тот класс сделать template - и это не имеет конца. Пережить несколько неприятных switch несравненно проще

Да хоть бы и чисто теоретически
Код
C++ (Qt)
template <class T>
class CModel {
..
vector <T> mCoord;
};
 
Почему каждый (даже тот кто mCoord никак не использует) должен заниматься спецификацией CModel и копаться в подробностях формата точек? Где же инкапсуляция?
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #44 : Март 26, 2012, 14:47 »

Цитировать
Почему каждый (даже тот кто mCoord никак не использует) должен заниматься спецификацией CModel и копаться в подробностях формата точек? Где же инкапсуляция?
Ну если не использует, то и копаться не придётся..
Код
C++ (Qt)
template <class T>
void someMethod(CModel<T> &x) {
  x.someNonTemplateParametr = value; // ну и т.д.
}
 
Неужели так уж неприемлемо над каждой функцией template<class T> написать?
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Страниц: 1 2 [3] 4 5 6   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.327 секунд. Запросов: 22.