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

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

Голосование
Вопрос: Почему QPoint/QVector не template ?
Меньше template = лучше - 1 (14.3%)
Тролли всегда правы - 0 (0%)
Потому что это UI - 2 (28.6%)
Правильно что нет, потому что..) - 1 (14.3%)
Ваш вариант - 3 (42.9%)
Всего голосов: 7

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: Почему QPoint/QVector не template ?  (Прочитано 20200 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Июль 05, 2016, 07:55 »

Добрый день

Это уже не раз упоминалось, но все-таки

QPoint
QPointF
QVector2D
QVector3D
QVector4D

Оснований обобщать выше крыши, даже невооруженным глазом видно что все они прекрасно ложатся в один template класс. Тем не менее идет дубляж (весьма ощутимый). Почему?

Спасибо
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #1 : Июль 05, 2016, 08:38 »

Первые три можно было бы и затемплейтить, но вот с 3д и 4д вряд ли получится.
Но мне кажется, ответ простой - каждый класс писала своя, независимая команда индусов. А потом помержили и не стали менять легаси.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #2 : Июль 05, 2016, 14:26 »

Первые три можно было бы и затемплейтить, но вот с 3д и 4д вряд ли получится.

Можно затеплейтить любую размерность (что и сделано во многих других библиотеках), только векторное произведение непривычное получается.
« Последнее редактирование: Июль 05, 2016, 14:30 от ssoft » Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #3 : Июль 05, 2016, 14:55 »

Я имел в виду, что QPoint, QPointF и QVector2D имеют по 2 измерения, и поэтому их можно объединить в один темплейт. QVector3D уже трехмерный и поэтому для него потребуется отдельный темплейт и т.д.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Июль 05, 2016, 15:20 »

Я имел в виду, что QPoint, QPointF и QVector2D имеют по 2 измерения, и поэтому их можно объединить в один темплейт. QVector3D уже трехмерный и поэтому для него потребуется отдельный темплейт и т.д.
Ну и что? Чем мешает 3-я координата?

Лично я не могу объяснить почему. Возможно неуклонное следование правилу "одна сущность - один класс". См QPointF и QVector2D. Действительно "точка" и "вектор" - разные сущности. Но в декартовых координатах они "обратимы" - любую точку можно рассматривать как вектор из начала координат, и наоборот. Что впрочем не распространяется на все системы координат.

Можно затеплейтить любую размерность (что и сделано во многих других библиотеках), только векторное произведение непривычное получается.
Я чаще встречал подход как в Qt - отдельный класс на каждый
Записан
Bepec
Гость
« Ответ #5 : Июль 05, 2016, 15:29 »

Мб ещё потому, что тролли не любят темплейты.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #6 : Июль 05, 2016, 15:44 »

Ну и что? Чем мешает 3-я координата?

Как одним темлейтом описать и QPoint, и QVector3D ?
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #7 : Июль 05, 2016, 18:06 »

Почему?

Потому, что в объектном коде всё равно получится дубляж.
Зато, так не надо запрещать QPoint<void> QPoint<bool>, QPoint<QString>, а также нет гемора с QPoint<qint64> <-> QPoint<double>.
А еще QVariant::toPoint - делать его шаблонным?
Vector2D - это обертка над точкой, а не точка.
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #8 : Июль 05, 2016, 21:21 »

Как одним темлейтом описать и QPoint, и QVector3D ?

Обычно обобщают отдельно Point и Vector, так как они имеют разно поведение в применении операций суммирования, умножения деления и т.п.

Код
C++ (Qt)
template < typename _Type, int _D >
class Point
{
   _Type m_values[_D];
}
template < typename _Type, int _D >
class Vector
{
   _Type m_values[_D];
}
 

НО! Бывает обобщают и одним типом, добавляя дополнительную размерность и значение 0 для вектора и 1 для точки (как в OpenGL). Это значение и определяет поведение точки или вектора в матричных вычислениях. Упрощенно может выглядеть так

Код
C++ (Qt)
template < typename _Type, int _D >
class Base
{
   _Type m_values[_D+1];
}
template < typename _Type, int _D >
class Vector : public Base< _Type, _D >
{
public:
   Vector() {m_values[_D] = Type(); }
};
 
template < typename _Type, int _D >
class Point : public Base< _Type, _D >
{
public:
   Point() {m_values[_D] = Type(1); }
};
 
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #9 : Июль 05, 2016, 21:25 »

или еще проще

template < typename _Type, int _D >
class Cluster
{
    _Type m_values[_D+1];

public:
    static Cluster< _Type, _D > make_point ();
    static Cluster< _Type, _D > make_vector ();
}
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Июль 06, 2016, 06:43 »

Обычно обобщают отдельно Point и Vector, так как они имеют разно поведение в применении операций суммирования, умножения деления и т.п.
В декартовых координатах - совершенно одинаковое  Улыбающийся

НО! Бывает обобщают и одним типом, добавляя дополнительную размерность и значение 0 для вектора и 1 для точки (как в OpenGL). Это значение и определяет поведение точки или вектора в матричных вычислениях.
Ну вот почему никто не задаст простых естественных вопросов, напр
Цитировать
А как оно определяет? И зачем добавлять размерность?
Улыбающийся

Грубое объяснение:
Код
C++ (Qt)
vec.x = vec.x * some_constant / vec.z;
vec.y = vec.y * some_constant / vec.z;
Это перспективное преобразование - чем больше z тем меньше становятся x и y (точка стремится к центру экрана). Легко заметить что оно НЕ матричное (не ахвинное), первое же его применение разрушит цепочку матричных преобразований. Поэтому его и не применяют (не делят), а таскают этот делитель с собой - в той самой 4-й координате. Тогда матричные преобразования остаются корректными. А когда все вычисления/шейдеры закончились и надо рендерить - соскакивают в декартовы, делитель уже не нужен.

Однако вернемся к злополучным темплейтам. С точки зрения использования. Сейчас немало повторов типа
Код:
void QPainter::drawLine(const QPoint & p1, const QPoint & p2);
void QPainter::drawLine(const QPointF & p1, const QPointF & p2);[/quote]
Можно было бы так
Код:
template <class Point>
void QPainter::drawLine(const Point & p1, const Point & p2);
Хмм... ну как-то не вижу ничего плохого  Улыбающийся
Записан
Bepec
Гость
« Ответ #11 : Июль 06, 2016, 07:56 »

Чем более вы хотите обобщить класс, тем менее специализированным он становится.
При текущем положении дел, класс получивший QPoint или QPointF знает, какую точность от него требуют и какую операцию.
Получивший же обобщенный темплейт, потребует дополнительные флаги. Более того, теряется контроль ошибок аргументов.

НУ и в общем и целом - преждевременная оптимизация налицо. Сначала вы проверьте все классы, сравните работу с QPoint и QPointF, проанализируйте, что будет при замене одного на другого, какие погрешности у вас выплывут, какие косячные ситуации получатся и сколько классов получат "возможности", не предусмотренные разработчиками.

И таки это правильный подход - мухи отдельно, суп отдельно.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #12 : Июль 06, 2016, 09:09 »

Получивший же обобщенный темплейт, потребует дополнительные флаги.
Нельзя получить темплейт, вообще нельзя. Можно получить объект класса, созданного из шаблона, но тогда это уже полностью специализированный шаблон, знающий все типы. Ну и никаких дополнительных флагов не понадобиться.

Более того, теряется контроль ошибок аргументов.
Да вы что? Улыбающийся
Шаблоны и придумывали, что бы была возможность контролировать эти аргументы. Это то что не может сишный препроцессор.
Записан
Bepec
Гость
« Ответ #13 : Июль 06, 2016, 10:46 »

Вы придираетесь к словам, я верю что у вас достаточно ума, чтобы понять смысл фразы, а не смысл отдельных слов.

Функция, принимающая int и float, не будет знать, когда использовать int, а когда float. А так же будет запутанным поведение при смешении аргументов и как следствие неопределённое поведение для программиста.

Точнее это реализуемо, но при этом гораздо более сложно, чем две функции с разными классами.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #14 : Июль 06, 2016, 11:36 »

Цитировать
Функция, принимающая int и float, не будет знать, когда использовать int, а когда float

C++ умеет перегрузку функций...
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


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