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

Войти
 
  Начало   Форум  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 ?  (Прочитано 20196 раз)
Bepec
Гость
« Ответ #15 : Июль 06, 2016, 12:09 »

Перегрузка со одинаковыми параметрами? Это как?
Т.е. вы можете реализовать вот эти две РАЗНЫЕ функции?
На примере повторов
Код:
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);
void QPainter::drawLine(const Point & p1, const Point & p2);

Т.е. при обобщении мы сможем вызвать как
drawLine(QPoint(int,int), QPoint(int,int)), так и drawLine(QPoint(float,float), QPoint(float,float)). Но различия в функциях скорее всего есть и будут. И вот как в данном случае поступить?  Разве что внутри свичи ставить с типами.
« Последнее редактирование: Июль 06, 2016, 12:14 от Bepec » Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


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


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

QPoint и QPointF - разные типы. Не вижу проблемы.
Записан

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


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

Функция, принимающая int и float, не будет знать, когда использовать int, а когда float.
Она легко может это узнать
Код
C++ (Qt)
if (std::is_floating_point<pt.x()>::value) ...
или аккуратнее
if (std::is_floating_point<Point::value_type>::value) ...
или даже без С++ 11
if (typeid(Point::value_type) == typeid(float)..
 
Но различия в функциях скорее всего есть и будут.
Не исключено, но их мало по сравнению с массой дублируемого кода. А если для какой-то ф-ции это не так, то можно ее оставить как есть
Код
C++ (Qt)
typedef Point<int, 2> QPoint;
typedef Point<qreal, 2> QPointF;
 
void QPainter::drawLine(const QPoint & p1, const QPoint & p2);
void QPainter::drawLine(const QPointF & p1, const QPointF & p2);
 
И вообще не лучше ли сказать прямо, напр
Цитировать
Ну там наверное тоже не дураки, посчитали что выгоднее (по существу ответ 2)
Не вижу ничего зазорного в такой позиции, во всяком случае лучше чем барахтаться в чем-то наспех придуманном Улыбающийся И ведь просил же не пакостить в моих темах  Плачущий
Записан
Bepec
Гость
« Ответ #18 : Июль 06, 2016, 13:05 »

Просите сколь угодно.
to Racheengel: Igors говорит об обобщении этих двух типов в один шаблон. И потому никак не узнать, кроме свитчей и сравнивания типов, что пагубно влияет на читаемость и поддержку такого кода.
И именно поэтому выгоднее иметь 2 типа, которые не спутать и которые ясны для программиста.
Qt всё же имеет постулат - удобство важнее красоты кода. Возможно он и не звучит вслух, но явно прослеживается Улыбающийся
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


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

Она легко может это узнать
Код
C++ (Qt)
if (std::is_floating_point<pt.x()>::value) ...
или аккуратнее
if (std::is_floating_point<Point::value_type>::value) ...
или даже без С++ 11
if (typeid(Point::value_type) == typeid(float)..
 
Не исключено, но их мало по сравнению с массой дублируемого кода. А если для какой-то ф-ции это не так, то можно ее оставить как есть

При таком подходе мы получим, что ВСЕ ф-ии, принимающие Point<T, int Size> обязаны быть шаблонными => они будут инстанцироваться в пользовательском коде => размер бинаря вырастет как конь. Ничего ен напоминает?

Код
C++ (Qt)
typedef Point<int, 2> QPoint;
typedef Point<qreal, 2> QPointF;
 
void QPainter::drawLine(const QPoint & p1, const QPoint & p2);
void QPainter::drawLine(const QPointF & p1, const QPointF & p2);
 


А при таком подходе выигрыша почти нет. В бинарном коде копипаста будет в обоих случаях.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Просите сколь угодно.
Ага, типа
Цитировать
А я вот хочу говорить и БУДУ! И рот мне не закроете! И неважно что говорю полную фигню - ИМЕЮ ПРАВО!
Улыбающийся

Qt всё же имеет постулат - удобство важнее красоты кода.
Относительно недавно тут человеку понадобилось "все то же самое что QVector3D" но только "double" (а не "float"). И пришлось сносить QVector3D и прикручивать стороннюю либу. Это как, удобно?
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


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

И пришлось сносить QVector3D и прикручивать стороннюю либу. Это как, удобно?

Это нормально, если целевая платформа не поддерживает double.
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


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

Обычно обобщают отдельно 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-й координате. Тогда матричные преобразования остаются корректными. А когда все вычисления/шейдеры закончились и надо рендерить - соскакивают в декартовы, делитель уже не нужен.

Это не совсем так. Четвертую координату добавляют как раз для того, чтобы в декартовых координатах ввести разницу между понятиями Point и Vector при их обобщении в алгебраических операциях. Но это чисто математический трюк).

Например, результат операции point + point является невалидным (даже логически неясно, что имеется в виду), так как четвертая координата будет равна 2, а вот результат операции нахождения средины отрезка 0.5 * ( point + point ) уже валиден. В то же время операции с вектором обе валидны. Вектор является инвариантной величиной, а точка - нет. Это означает что изменение положения точки начала отсчета на компоненты вектора никак не повлияет, а на координаты точки - повлияет.

Операции масштабирования осуществляется с помощью первых трех компонент матрицы на диагонали (четвертый всегда равен 1), а операция перемещения осуществляется с помощью трех компонент 4-го столбца матрицы. Таким образом операция перемещения на точки действует, а на векторы - нет.

В отображении участвуют всегда только точки, при этом четвертая компонента может быть использована для проверки валидности произведенных расчетов, так как должна быть равна 1 (с учетом вычислительных погрешностей).
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


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

По теме шаблонов для точки и вектора.
Так получилось, что много работаю с геометрией и графикой, которые имеют различную точность представления. Графические точки - float, геометрические - double или с повышенной точностью (http://neerc.ifmo.ru/wiki/index.php?title=Adaptive_precision_arithmetic). Без шаблонного их представления здесь просто не обойтись.
Реализация QPoint и QPointF весьма убога в геометрическом смысле, эти типы удобны для использования только в GUI. Отсутствие шаблонной реализации в Qt, скорее всего, связано с политикой простоты вхождения для новичков, хотя по сути это копипаст. Инструмент Qt позиционируется, как легкий в использовании, и не требующий глубоких познаний языка программирования, поэтому они всячески избегают шаблонов в API.
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


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


Просмотр профиля
« Ответ #24 : Июль 07, 2016, 16:54 »

ну, point + point = point, не вижу проблем)
Записан

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


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

Это не совсем так. Четвертую координату добавляют как раз для того, чтобы в декартовых координатах ввести разницу между понятиями Point и Vector при их обобщении в алгебраических операциях. Но это чисто математический трюк).
Ну это уже не декартовы координаты, а "однородные". Факт отличия вектор/точка конечно любопытен, но и только - какая от него польза? Мне известно только одно реальное применение - положить перспективу под матрицу. И то, правду сказать, какой-то абсолютной необходимости в этом не вижу. Перспективное преобразование или последнее в цепочке ("в экран") или первое при обратном. Ну поделил/помножил - потом уже матрицы.

ну, point + point = point, не вижу проблем)
Если строго следовать "сущностям" то такое сложение бессмысленно. Складываются вектора - для них эта операция определена. Очевидно что
Цитировать
point - point = vector
Ведь "разница между позициями" сама по себе не позиция. А что такое "сумма точек" - хз. Поэтому проще в эти подробности не углубляться, просто в декартовых координатах с чистой совестью можно рассматривать точку как вектор - и наоборот
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Без шаблонного их представления здесь просто не обойтись.
Реализация QPoint и QPointF весьма убога в геометрическом смысле, эти типы удобны для использования только в GUI. Отсутствие шаблонной реализации в Qt, скорее всего, связано с политикой простоты вхождения для новичков, хотя по сути это копипаст. Инструмент Qt позиционируется, как легкий в использовании, и не требующий глубоких познаний языка программирования, поэтому они всячески избегают шаблонов в API.
Так а что GUI - не люди что ли?  Улыбающийся

Ладно, попробовал прошагать тот же самый пример drawLine
Код
C++ (Qt)
inline void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
{
   QLine l(p1, p2);
   drawLines(&l, 1);
}
 
void QPainter::drawLines(const QLine *lines, int lineCount)
{
   Q_D(QPainter);
 
   if (!d->engine || lineCount < 1)
       return;
 
   if (d->extended) {
       d->extended->drawLines(lines, lineCount);
..
 
void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount)
{
   Q_D(QRasterPaintEngine);
   QRasterPaintEngineState *s = state();
 
   ensurePen();
   if (!s->penData.blend)
       return;
 
   if (s->flags.fast_pen) {
       QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
       stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
       for (int i=0; i<lineCount; ++i) {
           const QLine &l = lines[i];
           stroker.drawLine(l.p1(), l.p2());
..
 
void QCosmeticStroker::drawLine(const QPointF &p1, const QPointF &p2)
{
..
 
Если исходные точки были QPointF, то все точно так же, сдублированные методы void QPainter::drawLines и QRasterPaintEngine::drawLines выглядят одинаково. Все равно все сводится к QCosmeticStroker::drawLine который уже не имеет вариантов а принимает QPointF. 

Тут пришла простая мысля - ну а какой должна быть организация файлов/проекта если хотим template? Выходит QPainter::drawLines нужно тащить в хедер? И QRasterPaintEngine::drawLines тоже? И еще много-много всего? Как-то выходит "все кишки наружу", причем со всеми private подробностями
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


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

Без шаблонного их представления здесь просто не обойтись.
Реализация QPoint и QPointF весьма убога в геометрическом смысле, эти типы удобны для использования только в GUI. Отсутствие шаблонной реализации в Qt, скорее всего, связано с политикой простоты вхождения для новичков, хотя по сути это копипаст. Инструмент Qt позиционируется, как легкий в использовании, и не требующий глубоких познаний языка программирования, поэтому они всячески избегают шаблонов в API.
Так а что GUI - не люди что ли?  Улыбающийся

Ладно, попробовал прошагать тот же самый пример drawLine
Код
C++ (Qt)
inline void QPainter::drawLine(const QPoint &p1, const QPoint &p2)
{
   QLine l(p1, p2);
   drawLines(&l, 1);
}
 
void QPainter::drawLines(const QLine *lines, int lineCount)
{
   Q_D(QPainter);
 
   if (!d->engine || lineCount < 1)
       return;
 
   if (d->extended) {
       d->extended->drawLines(lines, lineCount);
..
 
void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount)
{
   Q_D(QRasterPaintEngine);
   QRasterPaintEngineState *s = state();
 
   ensurePen();
   if (!s->penData.blend)
       return;
 
   if (s->flags.fast_pen) {
       QCosmeticStroker stroker(s, d->deviceRect, d->deviceRectUnclipped);
       stroker.setLegacyRoundingEnabled(s->flags.legacy_rounding);
       for (int i=0; i<lineCount; ++i) {
           const QLine &l = lines[i];
           stroker.drawLine(l.p1(), l.p2());
..
 
void QCosmeticStroker::drawLine(const QPointF &p1, const QPointF &p2)
{
..
 
Если исходные точки были QPointF, то все точно так же, сдублированные методы void QPainter::drawLines и QRasterPaintEngine::drawLines выглядят одинаково. Все равно все сводится к QCosmeticStroker::drawLine который уже не имеет вариантов а принимает QPointF. 

Тут пришла простая мысля - ну а какой должна быть организация файлов/проекта если хотим template? Выходит QPainter::drawLines нужно тащить в хедер? И QRasterPaintEngine::drawLines тоже? И еще много-много всего? Как-то выходит "все кишки наружу", причем со всеми private подробностями

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

Сообщений: 2679


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


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

скорость компиляции тоже роль играет, темплейты медленные.
Записан

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


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

скорость компиляции тоже роль играет, темплейты медленные.

Скорость выполнения на темплейтах часто быстрее), так как компиляторы тщательнее оптимизируют код и многое вычисляется на этапе компиляции, даже если это специально и не просили каким-нибудь constexpr.
Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


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