Название: Шаблоны. Отправлено: Андрей от Март 24, 2012, 11:41 Могу ли я наследовать класс от шаблона следующим образом?
Код
Название: Re: Шаблоны. Отправлено: mutineer от Март 24, 2012, 12:11 Ну вроде все в порядке, можешь наследоваться. Только не уверен нормально ли будет форвард-декларэйшн VWord. А из-за чего вопрос? компил ругается?
Название: Re: Шаблоны. Отправлено: Igors от Март 24, 2012, 12:27 "Пользуйтесь тегом для оформления кода" (а то читать неудобно)
Indexes = Indices (а лучше просто везде Index) По существу: унаследоваться можете, и getWordVersion, incrWordVersion будут работать, но "задействовать их в виртуальных целях" не получится Название: Re: Шаблоны. Отправлено: Андрей от Март 24, 2012, 14:01 Ругается...
Решил шаблоны освоить. Написал шаблон. Шаблон типонезависимый и не знает полей классов Ti и Tp. Описал частично его методы, понял что кое-где гораздо удобней, когда класс знает типы классов Ti и Tp. Решил что нужно от него наследовать класс и в классе переопределять некоторые методы в зависимости от типов. Вынес шаблон в отдельные cpp/h. Планирую описать там два шаблона VVectorIndex и VListIndex. При компиляции выдаёт Код: ошибка: undefined reference to `VVectorIndex<unsigned short, VWord>::createIndex(VWord*)' Код: VWordIndex(QObject* parent = 0):VVectorIndex<unsigned short, VWord>(parent){}; Код: ошибка: undefined reference to `VVectorIndex<unsigned short, VWord>::VVectorIndex(QObject*)' Название: Re: Шаблоны. Отправлено: Андрей от Март 24, 2012, 14:08 Т.е. вообще нельзя "задействовать методы в виртуальных целях" наследуя от шаблона. А деструктор?
Название: Re: Шаблоны. Отправлено: m_ax от Март 24, 2012, 14:15 Т.е. вообще нельзя "задействовать методы в виртуальных целях" наследуя от шаблона. А деструктор? Да можно, нормально там всё) А ошибки у вас выскакивают из-за того, что объявление и реализация шаблонных классов/функций должны нах. в одной единице трансляции. Перенесите из cpp всё обратно в h и всё заработает) Название: Re: Шаблоны. Отправлено: Igors от Март 24, 2012, 14:21 Да можно, нормально там всё) Интересно как. Прошу показать как задействовать напр метод getWordVersion (принимающий template аргумент) в виртуальном механизмеНазвание: Re: Шаблоны. Отправлено: m_ax от Март 24, 2012, 14:33 Да можно, нормально там всё) Интересно как. Прошу показать как задействовать напр метод getWordVersion (принимающий template аргумент) в виртуальном механизмеДа легко: Код
Название: Re: Шаблоны. Отправлено: Igors от Март 24, 2012, 14:45 Да легко: Что легко-то? :) В Вашем примере virtual хоть есть хоть нету - все работает одинаково, виртуальный механизм никак не используетсяНазвание: Re: Шаблоны. Отправлено: m_ax от Март 24, 2012, 14:51 Да легко: Что легко-то? :) В Вашем примере virtual хоть есть хоть нету - все работает одинаково, виртуальный механизм никак не используетсяКак это не используется? А как же вот эта строчка: Код И далее: Код
Полиморфизм в чистом виде) Да, кстатии, архитектура libssc на этом построена) ЗЫ. Обычно, то, что хочет реализовать автор ветки, делают немного по другому.. Возможно следует покурить в сторону type_traits (классов характеристик) Название: Re: Шаблоны. Отправлено: Igors от Март 24, 2012, 15:24 Как это не используется? Так он заканчивается на <double>, напрА как же вот эта строчка: Код И далее: Код
Полиморфизм в чистом виде) Код Хотя оба могут делать print - это разные методы (полиморфные но никак не связанные между собой) и использовать их в общем виртуальном механизме не удается. Эффект virtual равен нулю ЗЫ. Обычно, то, что хочет реализовать автор ветки, делают немного по другому.. Возможно следует покурить в сторону type_traits (классов характеристик) Расскажите, мне тоже интересноНазвание: Re: Шаблоны. Отправлено: m_ax от Март 24, 2012, 16:16 Цитировать Так он заканчивается на <double>, напр Код
Хотя оба могут делать print - это разные методы (полиморфные но никак не связанные между собой) и использовать их в общем виртуальном механизме не удается. Эффект virtual равен нулю Так сами классы base<double> и base<float> - это два совершенно разных класса с точки зрения компилятора. Код Об этом уже много написано.. Типичный пример это std::numeric_limits<T> Если в двух словах: Код Это делает код более гибким, поскольку можно отдельно (независимо) писать свои типы характеристик, определяя их индивидуальное поведение, причём интерфейс класса, который их использует остаётся неизменным. В книжке "Философия С++" (2 часть) есть хороший пример, как это используется.. Название: Re: Шаблоны. Отправлено: Андрей от Март 24, 2012, 18:38 Спасибо. Скомпилил. На удивление больше ошибок не было. Хотя правил код, который писал в последний раз неделю назад, правил особо не вдумываясь:-)))
Только немного неудобно, когда всё в одном h-нике. Хорошо, хоть VWordIndex описал в другом h-нике отдельно от его срр кода. Созрею, почитаю - сделаю через traits. Название: Re: Шаблоны. Отправлено: m_ax от Март 24, 2012, 21:04 Спасибо. Скомпилил. На удивление больше ошибок не было. Хотя правил код, который писал в последний раз неделю назад, правил особо не вдумываясь:-))) Только немного неудобно, когда всё в одном h-нике. Хорошо, хоть VWordIndex описал в другом h-нике отдельно от его срр кода. Созрею, почитаю - сделаю через traits. Да может в вашей задаче нужно делать не обязательно через traits.. Всё зависит от постановки конкретной задачи. Но почитать об этом патерне всё равно стоит)) Название: Re: Шаблоны. Отправлено: mutineer от Март 25, 2012, 13:07 Решил шаблоны освоить. Написал шаблон. Шаблон типонезависимый и не знает полей классов Ti и Tp. Описал частично его методы, понял что кое-где гораздо удобней, когда класс знает типы классов Ti и Tp. Решил что нужно от него наследовать класс и в классе переопределять некоторые методы в зависимости от типов. Мне кажется, или тут правда можно обойтись специализацией шаблона? Название: Re: Шаблоны. Отправлено: m_ax от Март 25, 2012, 20:15 Решил шаблоны освоить. Написал шаблон. Шаблон типонезависимый и не знает полей классов Ti и Tp. Описал частично его методы, понял что кое-где гораздо удобней, когда класс знает типы классов Ti и Tp. Решил что нужно от него наследовать класс и в классе переопределять некоторые методы в зависимости от типов. Мне кажется, или тут правда можно обойтись специализацией шаблона? С другой стороны можно написать базовый класс, функционал которого не зависит от типа шаблона и наследоваться от него с последующей реализацией специализации.. Но опять-таки здесь всё зависит от конкретной задачи.. Название: Re: Шаблоны. Отправлено: Igors от Март 25, 2012, 20:35 Можно, конечно сделать всё и через специализацию, но в таком случае ему придётся реализовывать весь функционал заново.. Давайте попробуем конкретизировать. Есть такие простые структурки которые хотим обощитьС другой стороны можно написать базовый класс, функционал которого не зависит от типа шаблона и наследоваться от него с последующей реализацией специализации.. Но опять-таки здесь всё зависит от конкретной задачи.. Код Конечно мы можем писать напр Код Но так мы очень быстро окажемся заваленными ф-циями/методами которые отличаются только типом вектора. И тогда придется делать еще template. Вместо этого мы хотим сделать "нормальный" базовый класс, его потомки уже будут template, а мы будем работать с базовым. Как это сделать? Название: Re: Шаблоны. Отправлено: m_ax от Март 25, 2012, 20:57 Можно, конечно сделать всё и через специализацию, но в таком случае ему придётся реализовывать весь функционал заново.. Давайте попробуем конкретизировать. Есть такие простые структурки которые хотим обощитьС другой стороны можно написать базовый класс, функционал которого не зависит от типа шаблона и наследоваться от него с последующей реализацией специализации.. Но опять-таки здесь всё зависит от конкретной задачи.. Код Конечно мы можем писать напр Код Но так мы очень быстро окажемся заваленными ф-циями/методами которые отличаются только типом вектора. И тогда придется делать еще template. Вместо этого мы хотим сделать "нормальный" базовый класс, его потомки уже будут template, а мы будем работать с базовым. Как это сделать? В данном случае нормальный базовый клас если и можно будет сделать, то только пустым.. Код
Но смысл в этом? Название: Re: Шаблоны. Отправлено: Igors от Март 25, 2012, 21:16 Я говорю о базовом классе контейнере, разные наследники которого будут хранить разные типы элементов.
Обобщать сами структуры - для простоты положим что это не нужно, в конце-концов результатом обобщения будут разные классы, и задача с контейнером никак не упрощается Edit: m_ax, просьба: цитированием не злоупотребляйте, а то длинная портянка получается :) Название: Re: Шаблоны. Отправлено: m_ax от Март 25, 2012, 21:22 Я говорю о базовом классе контейнере, разные наследники которого будут хранить разные типы элементов. Всё равно не понял, чем мотивировано такое поведение? Чем это отличается, скажем от простого typedef?Обобщать сами структуры - для простоты положим что это не нужно, в конце-концов результатом обобщения будут разные классы, и задача с контейнером никак не упрощается Edit: m_ax, просьба: цитированием не злоупотребляйте, а то длинная портянка получается :) Код В чём Вы видите выйгрыш от вашей задумки (я не совсем понимаю какого поведения Вы хотите добиться)? Название: Re: Шаблоны. Отправлено: Igors от Март 25, 2012, 21:34 В чём Вы видите выйгрыш от вашей задумки (я не совсем понимаю какого поведения Вы хотите добиться)? С точки зрения использованияКод CoordVec - базовый класс (контейнер), возможно абстрактный. Конкретный потомок может хранить Point в разных форматах, но делать template для CModel мне утомительно и нежелательно Название: Re: Шаблоны. Отправлено: m_ax от Март 25, 2012, 21:53 Ну если CoordVec может быть абстрактным, то можно сделать так (хотя это сомнительное решение, имхо)
Код
Если я правильно уловил суть. Ещё можно написать свой класс variant и создавать вектор Код А variant может быть чем угодно.. Ну типа аналог QVariant.. ??? Название: Re: Шаблоны. Отправлено: Igors от Март 25, 2012, 22:12 Да, template вещь полезная, но "выносит моск" капитально :) Давайте я еще раз попробую объяснить откуда "берется необходимость". Простейшее решение
Код Да, так все будет работать, НО template "проникает наверх". То есть везде где я использую CModel (а таких мест масса) я обязан буду "специфицироваться", объявить template во всех ф-циях и методах которые принимают/возвращают CModel. Это очень неудобно, т.к. у CModel есть множество др дел кроме mCoord, Если же я хочу сделать CModel членом др класса - еще хуже. Поэтому естественно желание "замкнуть" template в классе контейнера чтобы оно не лезло во все щели Название: Re: Шаблоны. Отправлено: m_ax от Март 25, 2012, 22:26 Тогда логично написать свой класс variant (есть уже готовые реализации), объявит
Код
А в variant уже записывать хоть PointF, хоть PointD, да и всё что душа пожелает) Название: Re: Шаблоны. Отправлено: Igors от Март 25, 2012, 22:48 А в variant уже записывать хоть PointF, хоть PointD, да и всё что душа пожелает) Это в данном случае не годится: Point xx - низкоуровневые POD структуры, никакие "обертки" недопустимы с точки зрения доп расходов по памяти и конвертацииА чем Вам не нравится template класс с non-template базовым ? Название: Re: Шаблоны. Отправлено: m_ax от Март 25, 2012, 23:02 Цитировать А чем Вам не нравится template класс с non-template базовым ? А как вы себе его представляете?Название: Re: Шаблоны. Отправлено: Igors от Март 25, 2012, 23:15 А как вы себе его представляете? Код
Название: Re: Шаблоны. Отправлено: m_ax от Март 25, 2012, 23:25 Ну можно и так. Я бы ещё в базовый класс добавил виртуальную функцию
Код Чтоб можно было сразу определить с чем имеем дело. Название: Re: Шаблоны. Отправлено: Igors от Март 25, 2012, 23:31 А как теперь реализовать такую ф-цию (ну или метод) не городя switch(ей)
Код ? Название: Re: Шаблоны. Отправлено: m_ax от Март 25, 2012, 23:47 Поскольку в базовом классе CoordVec нет никакого вектора, то во-первых придётся использовать либо dynamic_cast, либо static_cast если известно к чему приводить..
И так вы не избавитесь от switch или ему подобных проверок и т.д. В этом плане этот вариант, конечно проигрывает.. Да и вызов виртуальных функций - тож дороговато( (а если учесть, что это чтение/запись) Название: Re: Шаблоны. Отправлено: Igors от Март 25, 2012, 23:54 Поскольку в базовом классе CoordVec нет никакого вектора, то во-первых придётся использовать либо dynamic_cast, либо static_cast если известно к чему приводить.. Ну эти соображения очевидны. А подумать, толкнуть идейку? Или умеем только утешать PinkPink ? :)И так вы не избавитесь от switch или ему подобных проверок и т.д. В этом плане этот вариант, конечно проигрывает.. Да и вызов виртуальных функций - тож дороговато( (а если учесть, что это чтение/запись) Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 09:15 Цитировать Ну эти соображения очевидны. А подумать, толкнуть идейку? Или умеем только утешать PinkPink ? Ну на мой взгляд, самое правильное решение это сделать класс CModel шаблонным.Код Это лучше и быстрее будет работать, нежели наследование, виртуальные функции и т.д. Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 11:46 Да, есть ещё такая фишка, как определить принадлежность какого-либо объекта к конкретному классу/типу. Может будет где полезно:
Код Используется это так: Код Вывод будет таким: Код
Название: Re: Шаблоны. Отправлено: Igors от Март 26, 2012, 12:14 Ну на мой взгляд, самое правильное решение это сделать класс CModel шаблонным. Минусы такого решения подробно описаны в посте #22http://www.prog.org.ru/index.php?topic=21385.msg148020#msg148020 (http://www.prog.org.ru/index.php?topic=21385.msg148020#msg148020) Да, есть ещё такая фишка, как определить принадлежность какого-либо объекта к конкретному классу/типу. Может будет где полезно: С 3-мя базовыми классами уже 9 вариантов, с большим...Рассмотрим такое Код Здесь очевидно никаких проблем нет. Можем ли мы как-то выдернуть (как бы "привести") базовый класс к template когда нам нужно? Это звучит не очень грамотно, но Вы поняли идею. Ну или хотя бы число приведений было = числу базовых классов. Потому что таких ф-ций как Append достаточно и "обильно свитчеваться" не хочется Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 12:30 Цитировать Минусы такого решения подробно описаны в посте #22 А создавать базовые классы и определять туеву хучу виртуальных методов, это, конечно, достойная альтернатива))Цитировать Рассмотрим такое Код
Здесь очевидно никаких проблем нет. Можем ли мы как-то выдернуть (как бы "привести") базовый класс к template когда нам нужно? Это звучит не очень грамотно, но Вы поняли идею. Не совсем понял.. Я бы написал специализацию этой функции.. Код
Ну или что там под T1, T2 подразумевается.. Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 12:42 Идея написать свой базовый контейнер, имхо, пройгрышна.
Во-первых, по производительности. Во-вторых, добавляется ещё много всякого кода (базовый класс, наследники, виртуальные функции) В-третьих, страдает расширяемость и гибкость. Что если в будущем понадобится добавить ещё какой нить класс Точки? Всюду придётся переписывать всё.. Не гут( Название: Re: Шаблоны. Отправлено: Igors от Март 26, 2012, 13:05 А создавать базовые классы и определять туеву хучу виртуальных методов, это, конечно, достойная альтернатива)) Более чем. Даже если не существует хорошего решения для Append - я имею головную боль всего с одним классом, а в Вашем варианте - со всем приложением.Не совсем понял.. А откуда я возьму Point3D (или др) если известен только базовый класс (который не template)?Я бы написал специализацию этой функции.. Код
Идея написать свой базовый контейнер, имхо, пройгрышна. Зачем же мне всюду переписывать если классы верхнего уровня даже не знают о существовании разных форматов точек? :)... В-третьих, страдает расширяемость и гибкость. Что если в будущем понадобится добавить ещё какой нить класс Точки? Всюду придётся переписывать всё.. Не гут( Код
Во-первых, по производительности. Ага, а вот и результат общения с PinkPink :)Во-вторых, добавляется ещё много всякого кода (базовый класс, наследники, виртуальные функции) [offtop]Конечно чтение книг развивает и.т.п. Но в то же время читающий "оказывается под влиянием". Ход мыслей сводится к подстановке/перебору стандартных решений (часто пошленьких), активность/инициатива подавляется. Если в книжке такого не находится, то это немедленно объявляется (позорным) велосипедом. Увы, это работает даже для тех людей у которых с креативом все нормально :) Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 13:13 По поводу функции Append:
Её можно сделать так: Код Если для конкретного типа Point (пусть для определённости PointF) реализация будет отлична от общей, то логично просто написать специализацию: Код
Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 13:29 У меня как-то была похожая задачка. Нужно было реализовать некий класс, который использовал контейнер, но важно было дать возможность пользователю самому выбирать тип контейнера (вектора). Это, например мог быть и std::vector, и valarray и std::array, и даже std::complex (как двумерный вектор). Через шаблоны получилось очень прикольно)
Могу привести код) Название: Re: Шаблоны. Отправлено: Igors от Март 26, 2012, 13:38 Если для конкретного типа Point (пусть для определённости PointF) реализация будет отлична от общей, то логично просто написать специализацию: С этим ясно, также для простоты предположим все базовые структуры могут присваиваться друг другу, это легко обеспечить. Но где мне взять тип? Давайте набросаем первый (пусть уродливый) вариантКод Конечно это ужасно :) Но при полном отсутствии лучшего на это можно пойти. Хорошо, как это можно сделать лучше - или хотя бы менее болезненно? У меня как-то была похожая задачка. Нужно было реализовать некий класс, который использовал контейнер, но важно было дать возможность пользователю самому выбирать тип контейнера (вектора). Это, например мог быть и std::vector, и valarray и std::array, и даже std::complex (как двумерный вектор). Через шаблоны получилось очень прикольно) Идею поясните, а с кодом я разберусьМогу привести код) Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 14:01 Цитировать С этим ясно, также для простоты предположим все базовые структуры могут присваиваться друг другу, это легко обеспечить. Но где мне взять тип? Давайте набросаем первый (пусть уродливый) вариант Тип шаблона легко определить. Например так:Код
Теперь можно Ваш авариант функции Append написать через шаблоны: Код
Ну как то так это видится.. Название: Re: Шаблоны. Отправлено: Igors от Март 26, 2012, 14:14 Теперь можно Ваш авариант функции Append написать через шаблоны: Если бы я мог записать напр vector<Point>& dst - то тело ф-ции выписывается прекрасно без всяких switch. Но беда в том что аргументом(и) должен быть базовый класс который не templateКод
Ну как то так это видится.. Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 14:17 Цитировать Если бы я мог записать напр vector<Point>& dst - то тело ф-ции выписывается прекрасно без всяких switch. Но беда в том что аргументом(и) должен быть базовый класс который не template Ну так может и не стоит порождать базовый класс и его наследников, а сразу сделать через шаблоны?Я просто не могу понять (несколько раз читал пост 22) чем же всё-таки вариант с шаблоном не устраивает? Я пока не вижу проблемы.. Название: Re: Шаблоны. Отправлено: Igors от Март 26, 2012, 14:40 Ну так может и не стоит порождать базовый класс и его наследников, а сразу сделать через шаблоны? Меня совершенно не устраивает что все (абсолютно все) что хоть как-то связано с таким контейнером сразу же само становится template и требует спецификации. Добавили такой контейнер к чему-то (напр как член класса) - извольте и тот класс сделать template - и это не имеет конца. Пережить несколько неприятных switch несравненно прощеЯ просто не могу понять (несколько раз читал пост 22) чем же всё-таки вариант с шаблоном не устраивает? Я пока не вижу проблемы.. Да хоть бы и чисто теоретически Код Почему каждый (даже тот кто mCoord никак не использует) должен заниматься спецификацией CModel и копаться в подробностях формата точек? Где же инкапсуляция? Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 14:47 Цитировать Почему каждый (даже тот кто mCoord никак не использует) должен заниматься спецификацией CModel и копаться в подробностях формата точек? Где же инкапсуляция? Ну если не использует, то и копаться не придётся..Код Неужели так уж неприемлемо над каждой функцией template<class T> написать? Название: Re: Шаблоны. Отправлено: Igors от Март 26, 2012, 14:56 Неужели так уж неприемлемо над каждой функцией template<class T> написать? Даже в среднем проекте - совершенно неприемлемо, ведь это коснется очень многих ф-ций, методов и классовm_ax, думать будем или так, жопка к жопке из книжки тулить? :) У меня дела, появлюсь завтра, надеюсь увидеть что-то содержательное, пусть спорное, обсудим Название: Re: Шаблоны. Отправлено: whitecemetery от Март 26, 2012, 16:24 А я вот не понял следующее:
- кто, на каком этапе должен определять, какой тип точки используется внутри CModel? - разные объекты CModel могут использовать разные типы точек или нет? А то получается парадокс - я использую объект CModel, но ни я при его создании, ни кто-либо еще в другом месте не сказал о том, какой тип точки лежит внутри него. Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 16:34 А я вот не понял следующее: - кто, на каком этапе должен определять, какой тип точки используется внутри CModel? - разные объекты CModel могут использовать разные типы точек или нет? А то получается парадокс - я использую объект CModel, но ни я при его создании, ни кто-либо еще в другом месте не сказал о том, какой тип точки лежит внутри него. Я подозреваю, что CModel'и вообще фиолетово какой она контейнер содержит, не то что сами типы точек)) Контейнер то предполагается абстрактный.. Согласитесь, бредовая идея) Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 17:10 Короче вот вам окончательный костыль.
Пусть есть базовый класс base и от него нужно породить такие классы, как derived<PointF>, derived<PointX>.. Тогда делаем так: Код Примерно так. Как реализовать traits я уже писал. Но это плохое решение. Название: Re: Шаблоны. Отправлено: BRE от Март 26, 2012, 17:39 Это не первая попытка Igors сделать такой "чудо-контейнер": http://www.prog.org.ru/topic_19547_0.html :)
Но это плохое решение. Точно. :)А хорошее решение, скорее всего, потребует большого рефакторинга многих классов, их связей и, мне кажется, никому не нужна (судя по вышеуказанной теме). Сойдет и так. :) Название: Re: Шаблоны. Отправлено: Igors от Март 26, 2012, 20:19 Приехал раньше от заказчика, подключаюсь.
Вопросы whitecemetery приятно порадовали А я вот не понял следующее: Исключительно "создатель модели" который может быть всяким-разным (читатель файла, модельный плагин и.т.п)- кто, на каком этапе должен определять, какой тип точки используется внутри CModel? - разные объекты CModel могут использовать разные типы точек или нет? Да. Более того, существует много данных "точки" и они в разном формате для разных экземпляров CModelКод Каждый генератор модели имеет право создавать перечисленные данные (все или какие считает нужным) и выбрать нужный формат. Причесать все "под одну гребенку" никак не хорошо. Напр частенько mSpaceUV - всего 2 float, но может и 3, mNURBS - в основном 4, но бывает и 3, сами mPosition - как правило 3 double но могут быть и 3 float. короче - число вариантов быстро растет. Банкротство "простейшего template" здесь очевидно, напр Код Бред собачий А то получается парадокс - я использую объект CModel, но ни я при его создании, ни кто-либо еще в другом месте не сказал о том, какой тип точки лежит внутри него. При создании - создатель отвечает за все. А при использовании - и не нужно (неправильно) знать. Для пользователя модели это выглядит такКод Типа "дай мне N-ю точку в формате что мне надо" Название: Re: Шаблоны. Отправлено: Igors от Март 26, 2012, 22:15 Это не первая попытка Igors сделать такой "чудо-контейнер": http://www.prog.org.ru/topic_19547_0.html :) Верно что не первый раз я пытаюсь это здесь обсуждать, но вот тема что Вы упомянули не имеет к этому никакого отношения :)Но это плохое решение. Да это вообще хз что. Во-первых, чего Вы начинаете с того что это "костыль"? Тогда где же нормальное, правильное решение? Ах, Скуперфильд не пишет о нем в своей "философии"! Ну что ж поделать, друг мой, иногда приходится искать решения самому (а не только импозантно выглядеть перед глупенькими девушками). Во-вторых, откуда взялись паника и пораженческие настроения? Ну да, Append конечно совсем плох/коряв, но все же работает, и таких ф-ций (взаимодействие контейнер-контейнер) относительно немного - все остальное прекрасно ложится в виртуальный механизм. А про "замедление на виртуалах" лучше не заикайтесь. Так что, пацаны, слабО кинуть пару-тройку идеек как улучшить тот Append? Вся силенка ушла на нотации для нубов? Или как? :) Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 22:28 Ну как же Вы не понимаете, что в Ваших "реальных" задачах, вместо правильных решений приходится придумывать такие ходули, из-за того, что изначальна архитектура проекта была кривой и не продуманной.
Почему Вы такой вариант не принимаете? Название: Re: Шаблоны. Отправлено: BRE от Март 26, 2012, 22:39 Igors, скажу тебе по секрету, что язык программирования C++ является языком с сильной типизацией, поэтому такой подход (который ты пытаешься в очередной раз "решить") противоречит его главным идиомам. Соответственно никаких конструкций языка для обеспечения требуемого тебе поведения не может быть в принципе.
Ты, как разработчик на этом языке, должен всеми силами уходить от таких неопределенностей. Ты не должен хранить все числа в double, только потому что туда они помещаются (и char, и int, и ...), для проверки/приведения типов напридумывали всякие xxx_cast<>, для этого же придумали и шаблоны. Вся силенка ушла на нотации для нубов? А что делать, если у тебя столько вопросов.Название: Re: Шаблоны. Отправлено: Igors от Март 26, 2012, 22:41 Ну как же Вы не понимаете, что в Ваших "реальных" задачах, вместо правильных решений приходится придумывать такие ходули, из-за того, что изначальна архитектура проекта была кривой и не продуманной. Да очень даже принимаю. Я накосячил - я и отвечу. Только вот в упор не вижу где же "правильно" (пусть субъективно/спорно). Влепить template на всех - ну Вы же видите что никак. Задать все "по максимуму" - решение начинающего. Что нереального/выдуманного (или надуманного) в моей задаче? Погуглите 5 мин - и Вы увидите что любая 3D модель имеет данные что я привел - я их не брал с потолка. Моя изначальная архитектура кривая - хорошо, а как правильно? :)Почему Вы такой вариант не принимаете? Название: Re: Шаблоны. Отправлено: Igors от Март 26, 2012, 22:53 Igors, скажу тебе по секрету, что язык программирования C++ является языком с сильной типизацией, поэтому такой подход (который ты пытаешься в очередной раз "решить") противоречит его главным идиомам. Соответственно никаких конструкций языка для обеспечения требуемого тебе поведения не может быть в принципе. А что такого криминального в моем подходе? Чем он противоречит базовым принципам? Хочу сделать (один) класс который умеет хранить данные в разных форматах? Это что, "попытка интерпретирования в стиле Lisp"? :) (который ты пытаешься в очередной раз "решить") Почему жизнь ничему не учит? Вы же прекрасно понимаете: все что мне нужно я уже давно решил - просто хочу обсудить с умными людьми :)Название: Re: Шаблоны. Отправлено: BRE от Март 26, 2012, 22:58 А что такого криминального в моем подходе? Чем он противоречит базовым принципам? Хочу сделать (один) класс который умеет хранить данные в разных форматах? Компилятор не может проверить типы (реальные типы). А он это очень не любит.я уже давно решил Могу себе представить. ::)Название: Re: Шаблоны. Отправлено: m_ax от Март 26, 2012, 23:00 Ну если вы не знаете, я то от куда знаю? Я даже представления не имею что это за проект и как там всё устроено)
Есть догадки) Но мне лично, идея наследоваться от какого то базового класса, переопределять вирт. функции для каждого типа точек и т.д. правильным путём не кажется( Если с шаблонами совсем никак, то я бы сделал, как уже говорил, через патерн variant: Код И никакого наследования.. А во всех функциях, я бы имел: Код
А сам класс variant занимает не намного больше места, чем то, что он в себя включает. Возможный пример его реализации: Код
Да, counted_ptr можно заменить на std::shared_ptr Название: Re: Шаблоны. Отправлено: BRE от Март 26, 2012, 23:18 Если с шаблонами совсем никак, то я бы сделал, как уже говорил, через патерн variant: variant не очень хорош как раз с точки зрения контроля типов во время компиляции. Мое мнение, чем реже ты скатываешься к варианту, тем лучше. ;)Мы напрасно ушли от обсуждения задачи к реализации чуто-контейнера, а если вернутся, то можно предложить такой вариант. Вот код Igors: Код: if (model.mSpaceUV) { // UV имеются? А что значит крутим? Давайте тогда сделаем метод spin, который будет этим заниматься и возвращать результат. Тогда для кручения, клиентам этого объекта, будет не нужно знать как, кто, в чем храниться. Название: Re: Шаблоны. Отправлено: Igors от Март 27, 2012, 00:55 variant не очень хорош как раз с точки зрения контроля типов во время компиляции. Мое мнение, чем реже ты скатываешься к варианту, тем лучше. ;) Тот редкий случай когда Вы и я согласны :) Да, "вариант" - это уже на самый пожарный случай.А что значит крутим? Давайте тогда сделаем метод spin, который будет этим заниматься и возвращать результат. Тогда для кручения, клиентам этого объекта, будет не нужно знать как, кто, в чем храниться. Клиент может прекрасно жить не зная ненужных (ему) подробностей, напр (упрощенно)Код Клиенту в принципе-то нужно немного: Get/Set, и др стандартные операции с контейнером. Да, будут какие-то расходы на возврат по значению, на возможный перевод float <-> double, но они вполне приемлемы Ну если вы не знаете, я то от куда знаю? Виноват, немного подгрузил спецификой. Но в конце-концов (с точки зрения чисто программирования) почему мы должны рассматривать/планировать класс только с одним "таким членом"? А если "таких" будет 2 и больше? (как оно и есть)Но мне лично, идея наследоваться от какого то базового класса, переопределять вирт. функции для каждого типа точек и т.д. правильным путём не кажется( Всем нам что-то нравится или нет. Но как лучше? Вариант с "вариантом" уже обсуждался, он здесь просто неуместен, т.к. (возможно) миллионы POD точек не должны превратиться в что-то "умное" - они должны остаться столь же "тупыми" как они были созданыВообще объясните мне пожалуйста - ну откуда такой "полный минор"? Да, мы видим что ни один стандартный паттерн здесь не годится (насколько я знаю). Так что, обосраться и не жить, что ли? Есть довольно очевидное решение с базовым виртуальным классом (которое я и реализовал). Почему это "костыль", "велосипед", "вилы/грабли", тем более "против логики языка"? Только потому что так не писал Александреску (или кто-то еще)? Что же такого плохого мы делаем? Используем виртуальный механизм? Наследуемся template классом от non-template? И что с того, чем оно плохо? Есть лучшие задумки (с точки зрения связки/взаимодействия классов) - с удовольствием приму участие в обсуждении. По поводу Append - ну я его маленько раскрутил, там не все так мрачно. Но я никогда не любил ни template ни теорию вообще, поэтому, честно говоря, я (немного) надеялся увидеть лучшие решения от Вас Название: Re: Шаблоны. Отправлено: BRE от Март 27, 2012, 08:44 Клиент может прекрасно жить не зная ненужных (ему) подробностей, напр (упрощенно) А почему ты здесь используешь Set/GetPoint3F, а не Set/GetPoint3D или Set/GetPoint2F. Ты как здесь определил, что в чудо-контейнере точки как раз 3F? Надеешься?Код
Клиенту в принципе-то нужно немного: Get/Set, и др стандартные операции с контейнером. Да, будут какие-то расходы на возврат по значению, на возможный перевод float <-> double, но они вполне приемлемы Хорошо так "упрощать". То, сё и др. А на выходе получаем дублирование чуть ли не каждого метода для каждого возможного типа и сложная расширяемость такого контейнера. Для нового типа точки придется добавить свои методы в контейнер, и самое страшное добавить поддержку в клиенты этого класса.А то что твои решения для тебя всегда приемлемы это я знаю. :) Вообще объясните мне пожалуйста - ну откуда такой "полный минор"? Да, мы видим что ни один стандартный паттерн здесь не годится (насколько я знаю). Так что, обосраться и не жить, что ли? Есть довольно очевидное решение с базовым виртуальным классом (которое я и реализовал). Почему это "костыль", "велосипед", "вилы/грабли", тем более "против логики языка"? Только потому что так не писал Александреску (или кто-то еще)? Что же такого плохого мы делаем? Используем виртуальный механизм? Наследуемся template классом от non-template? И что с того, чем оно плохо? Недостатки такого решения не в том, что есть виртуальный базовый класс, а в том что для каждого типа точек нужна отдельная поддержка в коде, причем как на стороне самого контейнера, так и на стороне его клиента. Чем же это решение отличается от variant? Результат тот-же, только более ограниченный.Но я никогда не любил ни template ни теорию вообще, поэтому, честно говоря, я (немного) надеялся увидеть лучшие решения от Вас Вот из-за этого все проблемы. Сначала ты (ни любящий ничего) создаешь свое "решение", а потом надеешься на чудесное решение от кого-то в одну строчку, что бы особо ничего не пришлось переделывать и сразу стало зашибись.Название: Re: Шаблоны. Отправлено: Igors от Март 27, 2012, 09:59 А почему ты здесь используешь Set/GetPoint3F, а не Set/GetPoint3D или Set/GetPoint2F. Ты как здесь определил, что в чудо-контейнере точки как раз 3F? Надеешься? Никак не определял. Клиент не обязан подстраиваться под формат хранения (хотя и такая возможность есть). Он может попросить данные в нужном ему формате, сработает соотв конструктор или оператор =. Хорошо так "упрощать". То, сё и др. А на выходе получаем дублирование чуть ли не каждого метода для каждого возможного типа и сложная расширяемость такого контейнера. Для нового типа точки придется добавить свои методы в контейнер, и самое страшное добавить поддержку в клиенты этого класса. Как и Ваши решения приемлемы для Вас :) Появился новый тип базовых - придется добавить еще Get/Set и операторы для переливания - это все. Но базовых типов немного, это не проблема. Много получается комбинацийА то что твои решения для тебя всегда приемлемы это я знаю. :) Недостатки такого решения не в том, что есть виртуальный базовый класс, а в том что для каждого типа точек нужна отдельная поддержка в коде, причем как на стороне самого контейнера, так и на стороне его клиента. Чем же это решение отличается от variant? Результат тот-же, только более ограниченный. Ну вот не надо прикидываться непонимающим. В случае варианта мы меняем формат самого элемента, в нашем случае мы оперируем с доступом к элементам хранящимся в фиксированном формате. Это разница принципиальная. Никакого "чуда" (типа контейнер хранящий все на свете) не планировалось. Речь шла об узком круге базовых структур, никто не собирался хранить напр строки. Беда теоретиков в том что они пропускают специфику мимо ушей, а потом начинают доказывать что, мол, в общем виде это недостижимо. Так в общем никто и не просил.Вот из-за этого все проблемы. Сначала ты (ни любящий ничего) создаешь свое "решение", а потом надеешься на чудесное решение от кого-то в одну строчку, что бы особо ничего не пришлось переделывать и сразу стало зашибись. Почему Вы думаете что каждый кто поднимает тему - жадный нуб который хочет от Вас что-то получить? :) Я решал эту задачу так, интересно как бы делали другие, нормально. По поводу теории - я так вижу что не люблю я ее совершенно правильно. Если бы m_ax думал сам - он бы придумал в 100 раз лучше чем я. Но он оказался под влиянием глупых книг, зажался, скатился на шаблонные/банальные решения. Ото меньше надо читать всяких Скуперфильдов Название: Re: Шаблоны. Отправлено: BRE от Март 27, 2012, 10:26 Никак не определял. Клиент не обязан подстраиваться под формат хранения (хотя и такая возможность есть). Он может попросить данные в нужном ему формате, сработает соотв конструктор или оператор =. В контейнере лежит точка 2F, клиент запрашивает 3D - он что получит. Кто это должен отслеживать? Компилятор уже не может, ты ему ручки отбил.Это решение ничем не отличается от варианта и дело вовсе не в том меняем или не меняем мы тип элемента, а в том, что клиент понятия не имеет до реального вызова, что храниться в контейнере и может ли он работать с этим типом точек. Как и Ваши решения приемлемы для Вас :) Появился новый тип базовых - придется добавить еще Get/Set и операторы для переливания - это все. Но базовых типов немного, это не проблема. Много получается комбинаций Могут быть клиенты, которые определяют тип точки и пытаются подстроиться под него, Тогда появиться необходимость менять еще их. А если использовать такой контейнер повсеместно, то может оказаться, что править придется очень много.Если бы m_ax думал сам - он бы придумал в 100 раз лучше чем я. Но он оказался под влиянием глупых книг, зажался, скатился на шаблонные/банальные решения. Ото меньше надо читать всяких Скуперфильдов Это случиться не раньше, чем m_ax отбросит глупые условия постановки задачи, которые только ты считаешь приемлемыми.А книги зло, да. Название: Re: Шаблоны. Отправлено: Igors от Март 27, 2012, 11:10 В контейнере лежит точка 2F, клиент запрашивает 3D - он что получит. Кто это должен отслеживать? Компилятор уже не может, ты ему ручки отбил. Пример: хранимая точка 2F (0.25f. 1.0f). Возвращаемая точка 3D (0.25, 1.0, 0.0)Это решение ничем не отличается от варианта и дело вовсе не в том меняем или не меняем мы тип элемента, а в том, что клиент понятия не имеет до реального вызова, что храниться в контейнере и может ли он работать с этим типом точек. Снова Вы рассматриваете "слишком общий" случай. Как правило клиенту пофиг есть ли 3-я UV координата. Типичная задача - интерполировать UV. Ну клиент будет работать с 3-мя (возможно в double), данные - считываться и сохраняться напр как 2 float. Все нормально, др случаи см нижеМогут быть клиенты, которые определяют тип точки и пытаются подстроиться под него, Тогда появиться необходимость менять еще их. А если использовать такой контейнер повсеместно, то может оказаться, что править придется очень много. Да, такой вариант возможен. Напр клиент хочет развернуться с SSL и его все-таки не устраивает конвертация (пусть относительно дешевая). В конце-концов Append - это тоже пример когда нужен "конкретный тип" (а не общий механизм). В этом случае я (пока) не вижу др решений кроме (уродливого) switch. Предлагайте - обсудим. А просто так охаять чужую корову - ума не надо :)Это случиться не раньше, чем m_ax отбросит глупые условия постановки задачи, которые только ты считаешь приемлемыми. Ну понеслась.. "Это неправильные пчелы! Они дают неправильный мед!". Но где ж я возьму "правильных" (чтобы было точно по книжке)? :) Конечно я не имею права грузить Вас спецификой, но я никак не выдрючивался, не усложнял задачу, наоборот - максимально упростил как смог. Вы легко можете это проверить слегка погуглив.А книги зло, да. Книги - не зло, а иногда даже необходимы. Но мне кажется лучше прочитать меньше да осмыслить больше чем наоборот :) Название: Re: Шаблоны. Отправлено: m_ax от Март 27, 2012, 11:12 Согласен с BRE)
Вариант (variant) здесь будет более гибким как раз из-за того, что не нужно будет переопределять функции set/get для каждого типа точек. И вообще (с вариантом) само наследование отпадает. Но не подходит, ладно.. Остаётся вариант с наследованием и последующим переопределением гетеров, сетеров. Я же предлагал такой вариант (где в базовом класе будут только две шаблонные функции не виртуальные) Код
Чем этот вариант хуже того, где в базовый класс вводятся виртуальные функции для каждого типа точки? Название: Re: Шаблоны. Отправлено: Igors от Март 27, 2012, 11:28 Согласен с BRE) :'(Чем этот вариант хуже того, где в базовый класс вводятся виртуальные функции для каждого типа точки? А как Вы позовете такие get/set? Откуда клиент возьмет Derived:?Название: Re: Шаблоны. Отправлено: m_ax от Март 27, 2012, 11:39 Цитировать А как Вы позовете такие get/set? Откуда клиент возьмет Derived:? Да, это верно) Он же (клиент) его не знает..Ну тогда, следственно, все Ваши условия диктуют принять вариант с наследованием. А как ещё? Название: Re: Шаблоны. Отправлено: BRE от Март 27, 2012, 11:46 Ну понеслась.. "Это неправильные пчелы! Они дают неправильный мед!". Но где ж я возьму "правильных" (чтобы было точно по книжке)? :) Конечно я не имею права грузить Вас спецификой, но я никак не выдрючивался, не усложнял задачу, наоборот - максимально упростил как смог. Вы легко можете это проверить слегка погуглив. Вот именно понеслась... Ты формулируешь конкретную задачу (хочу такой контейнер) - нате, думайте... Но задача уродлива с рождения. Стоит изменить условия и возможно все будет получаться лучше. Может стоит разделить контейнеты для точек и UW, может стоит объединить точки и нормали, может ...Ну ты же не можешь нас грузить подробностями, поэтому нам остается тыкать палочкой твоего уродца. Название: Re: Шаблоны. Отправлено: m_ax от Март 27, 2012, 11:55 Цитировать А как Вы позовете такие get/set? Откуда клиент возьмет Derived:? Тогда вместо того, чтобы писать кучу функций на каждый тип точки, разумнее (имхо) написать один класс super точки, которая бы умела себя конвертировать и в PointF и в PointD и во что ей положено по условию..Тогда была бы всего одна функция get и одна функция set: Код Но, если у super_point будет сответствующие конструкторы, то в метод можно будет передовать непосредственно объекты и PointF и PointD и... Код
Сами же наследники будут хранить вектора соответствующих типов точек, а не super_point. Супер поинт - всего лишь некий адаптер между различными связанными между собой типами точек. Название: Re: Шаблоны. Отправлено: BRE от Март 27, 2012, 13:23 В контейнере лежит точка 2F, клиент запрашивает 3D - он что получит. Кто это должен отслеживать? Компилятор уже не может, ты ему ручки отбил. Пример: хранимая точка 2F (0.25f. 1.0f). Возвращаемая точка 3D (0.25, 1.0, 0.0)Т.е. какой-то нерадивый программист передает в функцию контейнер с UW, хотя функция ждет нормали и она начинает их обрабатывать. Это не пресекается не то что во время компиляции, а даже во время выполнения. Название: Re: Шаблоны. Отправлено: Igors от Март 27, 2012, 16:02 Но задача уродлива с рождения. Стоит изменить условия и возможно все будет получаться лучше. Может стоит разделить контейнеты для точек и UW, может стоит объединить точки и нормали, может ... Почему уродца-то? :) Здесь простая и естественная организация данных. Модель может иметь нормали и не иметь UV, а может и наоборот (хотя редко). Ну стало быть нормали и UV - 2 разных контейнера. Ну ты же не можешь нас грузить подробностями, поэтому нам остается тыкать палочкой твоего уродца. Тогда вместо того, чтобы писать кучу функций на каждый тип точки, разумнее (имхо) написать один класс super точки, которая бы умела себя конвертировать и в PointF и в PointD и во что ей положено по условию.. Хммм.. ну оно и сейчас примерно так и получается - близко к этому. Многочисленные конвертации можно вынести, а можно и прямо в базовом классаТогда была бы всего одна функция get и одна функция set: Хорошо, а что же делать в случаях если понадобился "конкретный" контейнер, не устраивает общий? Напр ф-ции OpenGL требуют указателей на float или double. Здесь особых проблем нет Код Ну и так по всем базовым типам. Не блеск конечно, но поскольку число базовых типов очень ограничено - нормально. А вот когда требуются 2 операнда "конкретных контейнера" - тогда хуже, получается громоздко Код Не то чтобы таких очень много, но есть, и это проблема Название: Re: Шаблоны. Отправлено: m_ax от Март 27, 2012, 16:21 Цитировать Не то чтобы таких очень много, но есть, и это проблема Адаптер очевидно писать нужно..Название: Re: Шаблоны. Отправлено: Igors от Март 27, 2012, 18:12 Ага, а если сделать super_point, то Append получается в неск строк - и без всяких switch. Уже хорошо! Может как-то еще лучше (без расходов на перегонку в super и обратно)?
Название: Re: Шаблоны. Отправлено: m_ax от Март 27, 2012, 18:34 Ага, а если сделать super_point, то Append получается в неск строк - и без всяких switch. Уже хорошо! Может как-то еще лучше (без расходов на перегонку в super и обратно)? Цель с которой водится адаптер (или хрен знает как его назвать) заключается в том, чтобы полностью исключить в клиентском коде (в функциях внешних) все явные приведения типов и т.п. Это всё делает адаптер, а на выходе выдаёт super_point, которая уже умеет конвертить себя к другим частным PointX. А уж вся ответственность за то, что было изначально в контэйнере и для чего предназначалось и что в результате получится в клиентском коде ложится на Вас)) Пугает какой то элемент неопределённости) Это как в рулетку играть) Название: Re: Шаблоны. Отправлено: Igors от Март 27, 2012, 18:50 Пугает какой то элемент неопределённости) Это как в рулетку играть) Есть такое, напр клиент рассчитывал на 3-ю координату, ее "физически" нет, но адаптер ее искусственно создаcт. Ну такому клиенту придется проверить Format(). Вообще на случаи 2/4 можно и забить (они встречаются в году раз) и просто считать что координат всегда 3. А вот отделаться от float/double никак не получается.А варианта с вмещающим super_point я не видел :) Конечно сейчас это кажется совсем простым. Спасибо (можете - когда хотите) Название: Re: Шаблоны. Отправлено: m_ax от Март 27, 2012, 19:23 Супер поинт - это обычная точка, но с доп возможностями:
Код В базовом классе тогда нужно будет определить два метода set и get: Код
Останется только адаптер написать. В c++11, за счёт того, что там появилась такая фича, как constexpr, его можно было бы особенно изящно реализовать... (без всяких switch) Название: Re: Шаблоны. Отправлено: Igors от Март 27, 2012, 20:05 А зачем мне еще какой-то адаптер? Просто так
Код Ну операторы для всех базовых определить (для переливания в TBigPoint и обратно). Вот и все Название: Re: Шаблоны. Отправлено: m_ax от Март 27, 2012, 20:18 Цитировать А зачем мне еще какой-то адаптер? Просто так Может и незачем.. Хотя кто Вас знает) Сегодня не надо, а завтра будет надо)Цитировать Ну операторы для всех базовых определить (для переливания в TBigPoint и обратно). Вот и все Не стоит делать так, чтоб к интерфейсу базовых точек PointF, PointD примешивался ещё и интерфейс SuperPoint. Они не должны о нём ничего знать. Только SuperPoint (он же BigPoint) может знать о них.. Иначе идейная чистота нарушается) Название: Re: Шаблоны. Отправлено: Igors от Март 27, 2012, 20:37 Не стоит делать так, чтоб к интерфейсу базовых точек PointF, PointD примешивался ещё и интерфейс SuperPoint. Они не должны о нём ничего знать. Не вижу чем это мне грозитТолько SuperPoint (он же BigPoint) может знать о них.. Иначе идейная чистота нарушается) Ничего, я это переживу :)А вот такая деталька: ведь SuperPoint может знать из чего он получен. Это никак не связано с темой, просто может (в будущем, при случае) удастся задействовать в корыстных целях Название: Re: Шаблоны. Отправлено: m_ax от Март 27, 2012, 20:53 Цитировать Не вижу чем это мне грозит Это лишние связи, которые ничего, кроме синтаксического сахара не дают.. Но за этот сомнительный сахар придётся платить лишим кодом в каждой базовой точке.Цитировать А вот такая деталька: ведь SuperPoint может знать из чего он получен. Это никак не связано с темой, просто может (в будущем, при случае) удастся задействовать в корыстных целях Тогда это уже будет жирная точка) |