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

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

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

Сообщений: 11445


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

Неужели так уж неприемлемо над каждой функцией template<class T> написать?
Даже в среднем проекте - совершенно неприемлемо, ведь это коснется очень многих ф-ций, методов и классов

m_ax, думать будем или так, жопка к жопке из книжки тулить? Улыбающийся  У меня дела, появлюсь завтра, надеюсь увидеть что-то содержательное, пусть спорное, обсудим
Записан
whitecemetery
Гость
« Ответ #46 : Март 26, 2012, 16:24 »

А я вот не понял следующее:
- кто, на каком этапе должен определять, какой тип точки используется внутри CModel?
- разные объекты CModel могут использовать разные типы точек или нет?
А то получается парадокс - я использую объект CModel, но ни я при его создании, ни кто-либо еще в другом месте не сказал о том, какой тип точки лежит внутри него.

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

Сообщений: 2095



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

А я вот не понял следующее:
- кто, на каком этапе должен определять, какой тип точки используется внутри CModel?
- разные объекты CModel могут использовать разные типы точек или нет?
А то получается парадокс - я использую объект CModel, но ни я при его создании, ни кто-либо еще в другом месте не сказал о том, какой тип точки лежит внутри него.

Я подозреваю, что CModel'и вообще фиолетово какой она контейнер содержит, не то что сами типы точек))
Контейнер то предполагается абстрактный.. Согласитесь, бредовая идея)
Записан

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

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

Сообщений: 2095



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

Короче вот вам окончательный костыль.
Пусть есть базовый класс base и от него нужно породить такие классы, как derived<PointF>, derived<PointX>..
Тогда делаем так:
Код
C++ (Qt)
enum PointType {TPointF, TPointX, TUnknown};
 
// Предварительное объявление
template <class T>
struct derived;
 
// класс base
struct base
{
   virtual ~base() {}
   virtual PointType type() const = 0;
 
   template <class T>
   T get(std::size_t index) const {
          switch(type()) {
          case TPointF: {
                derived<PointF> *d = static_cast<derived<PointF>*>(this);
                return d->vector[index];
          } break;
          case TPointX: {
                derived<PointX> *d = static_cast<derived<PointX>*>(this);
                return d->vector[index];
          } break;
       }
       return T();
   }
 
   template <class T>
   void set(std::size_t index, const T& val) {
       switch(type()) {
          case TPointF: {
                derived<PointF> *d = static_cast<derived<PointF>*>(this);
                d->vector[index] = val;
          } break;
          case TPointX: {
                derived<PointX> *d = static_cast<derived<PointX>*>(this);
                d->vector[index] = val;
          } break;
       }
   }
};
 
// Реализация derived
template <class T>
struct derived : public base
{
   virtual PointType type() const { return traits<T>::type(); }
   std::vector<T> vector;
};
 
// объявляем некую функцию, которая принимает базовый класс base
void func(base *x) {
  x->set(0, PointF(1,2,3))
  std::cout << x->get(0) << std::endl;
}
 
Примерно так. Как реализовать traits я уже писал.

Но это плохое решение.

Записан

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

Arch Linux Plasma 5
BRE
Гость
« Ответ #49 : Март 26, 2012, 17:39 »

Это не первая попытка Igors сделать такой "чудо-контейнер": http://www.prog.org.ru/topic_19547_0.html Улыбающийся

Но это плохое решение.
Точно. Улыбающийся
А хорошее решение, скорее всего, потребует большого рефакторинга многих классов, их связей и, мне кажется, никому не нужна (судя по вышеуказанной теме). Сойдет и так. Улыбающийся

« Последнее редактирование: Март 26, 2012, 17:42 от BRE » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Приехал раньше от заказчика, подключаюсь.

Вопросы whitecemetery приятно порадовали
А я вот не понял следующее:
- кто, на каком этапе должен определять, какой тип точки используется внутри CModel?
Исключительно "создатель модели" который может быть всяким-разным (читатель файла, модельный плагин и.т.п)

- разные объекты CModel могут использовать разные типы точек или нет?
Да. Более того, существует много данных "точки" и они в разном формате для разных экземпляров CModel
Код
C++ (Qt)
class CModel {
 ...
 CoordVec * mPosition;   // собственно координаты точек
 CoordVec * mNormal;    // нормали (перпендикуляры) к точкам
 CoordVec * mSрaceUV;  // позиции точек в UV(W) пространстве
 CoordVec * mBlur;        //  позиции motion blur
 CoordVec * mNURBS;
 
 // и.т.д  
};
 
Каждый генератор модели имеет право создавать перечисленные данные (все или какие считает нужным) и выбрать нужный формат. Причесать все "под одну гребенку" никак не хорошо. Напр частенько mSpaceUV - всего 2 float, но может и 3, mNURBS - в основном 4, но бывает и 3, сами mPosition - как правило 3 double но могут быть и 3 float. короче - число вариантов быстро растет.

Банкротство "простейшего template" здесь очевидно, напр

Код
C++ (Qt)
template <class T1. class T2. class T3... >
class CModel {
// вставить эту лабуду в проекте везде-везде
// и если у CModel появился новый член..
 
Бред собачий

А то получается парадокс - я использую объект CModel, но ни я при его создании, ни кто-либо еще в другом месте не сказал о том, какой тип точки лежит внутри него.
При создании - создатель отвечает за все. А при использовании - и не нужно (неправильно) знать. Для пользователя модели это выглядит так
Код
C++ (Qt)
// CModelUser
Point3F pt = model.mCoordinate->GetPoin3F(index);
if (model.mSpaceUV) {   // UV имеются?
// крутим UV
}
 
Типа "дай мне N-ю точку в формате что мне надо"
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Это не первая попытка Igors сделать такой "чудо-контейнер": http://www.prog.org.ru/topic_19547_0.html Улыбающийся
Верно что не первый раз я пытаюсь это здесь обсуждать, но вот тема что Вы упомянули не имеет к этому никакого отношения  Улыбающийся

Но это плохое решение.
Да это вообще хз что.

Во-первых, чего Вы начинаете с того что это "костыль"? Тогда где же нормальное, правильное решение? Ах, Скуперфильд не пишет о нем в своей "философии"! Ну что ж поделать, друг мой, иногда приходится искать решения самому (а не только импозантно выглядеть перед глупенькими девушками).

Во-вторых, откуда взялись паника и пораженческие настроения? Ну да, Append конечно совсем плох/коряв, но все же работает, и таких ф-ций (взаимодействие контейнер-контейнер) относительно немного - все остальное прекрасно ложится в виртуальный механизм. А про "замедление на виртуалах" лучше не заикайтесь.

Так что, пацаны, слабО кинуть пару-тройку идеек как улучшить тот Append? Вся силенка ушла на нотации для нубов? Или как?   Улыбающийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



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

Ну как же Вы не понимаете, что в Ваших "реальных" задачах, вместо правильных решений приходится придумывать такие ходули, из-за того, что изначальна архитектура проекта была кривой и не продуманной.
Почему Вы такой вариант не принимаете?

 
Записан

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

Arch Linux Plasma 5
BRE
Гость
« Ответ #53 : Март 26, 2012, 22:39 »

Igors, скажу тебе по секрету, что язык программирования C++ является языком с сильной типизацией, поэтому такой подход (который ты пытаешься в очередной раз "решить") противоречит его главным идиомам. Соответственно никаких конструкций языка для обеспечения требуемого тебе поведения не может быть в принципе.
Ты, как разработчик на этом языке, должен всеми силами уходить от таких неопределенностей. Ты не должен хранить все числа в double, только потому что туда они помещаются (и char, и int, и ...), для проверки/приведения типов напридумывали всякие xxx_cast<>, для этого же придумали и шаблоны.

Вся силенка ушла на нотации для нубов?
А что делать, если у тебя столько вопросов.
« Последнее редактирование: Март 26, 2012, 22:43 от BRE » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Ну как же Вы не понимаете, что в Ваших "реальных" задачах, вместо правильных решений приходится придумывать такие ходули, из-за того, что изначальна архитектура проекта была кривой и не продуманной.
Почему Вы такой вариант не принимаете?
Да очень даже принимаю. Я накосячил - я и отвечу. Только вот в упор не вижу где же "правильно" (пусть субъективно/спорно). Влепить template на всех - ну Вы же видите что никак. Задать все "по максимуму" - решение начинающего. Что нереального/выдуманного (или надуманного) в моей задаче? Погуглите 5 мин - и Вы увидите что любая 3D модель имеет данные что я привел - я их не брал с потолка. Моя изначальная архитектура кривая - хорошо, а как правильно?  Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Igors, скажу тебе по секрету, что язык программирования C++ является языком с сильной типизацией, поэтому такой подход (который ты пытаешься в очередной раз "решить") противоречит его главным идиомам. Соответственно никаких конструкций языка для обеспечения требуемого тебе поведения не может быть в принципе.
А что такого криминального в моем подходе? Чем он противоречит базовым принципам? Хочу сделать (один) класс который умеет хранить данные в разных форматах? Это что, "попытка интерпретирования в стиле Lisp"?  Улыбающийся

(который ты пытаешься в очередной раз "решить")
Почему жизнь ничему не учит? Вы же прекрасно понимаете: все что мне нужно я уже давно решил - просто хочу обсудить с умными людьми  Улыбающийся
Записан
BRE
Гость
« Ответ #56 : Март 26, 2012, 22:58 »

А что такого криминального в моем подходе? Чем он противоречит базовым принципам? Хочу сделать (один) класс который умеет хранить данные в разных форматах?
Компилятор не может проверить типы (реальные типы). А он это очень не любит.

я уже давно решил
Могу себе представить.  Строит глазки
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



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

Ну если вы не знаете, я то от куда знаю? Я даже представления не имею что это за проект и как там всё устроено)
Есть догадки)

Но мне лично, идея наследоваться от какого то базового класса, переопределять вирт. функции для каждого типа точек и т.д. правильным путём не кажется(

Если с шаблонами совсем никак, то я бы сделал, как уже говорил, через патерн variant:
Код
C++ (Qt)
struct super_vector
{
   TypeOfPoint type;
   std::vector<variant> vector;
};
 
И никакого наследования..
А во всех функциях, я бы имел:
Код
C++ (Qt)
void Append(super_vector& dst, const super_vector &src)
{
   if (dst.type == TPointF) {
       PointF p1 = dst.vector[index].get<PointF>();
       ...
       dst.vector[index] = PointF(1,2,3);
   }
 
}
 
 
А сам класс variant занимает не намного больше места, чем то, что он в себя включает.

Возможный пример его реализации:
Код
C++ (Qt)
struct base_data
{
   virtual ~base_data() {}
};
 
template <class T>
struct data : public base_data
{
   data() {}
   data(const T& val) : value(val) {}
   T value;
};
 
class variant
{
public:
   variant() {}
 
   template <class T>
   variant(const T& val) {
       _data = ssc::counted_ptr<base_data>(new data<T>(val));
   }
 
   template <class T>
   void set(const T& val) {
       _data = ssc::counted_ptr<base_data>(new data<T>(val));
   }
   template <class T>
   T get(bool *is_valid = 0) const {
       data<T> *d = dynamic_cast<data<T>*>(_data.get());
       if (d) {
           if (is_valid)
               *is_valid = true;
           return d->value;
       }
       if (is_valid)
           *is_valid = false;
       return T();
   }
 
   bool is_empty() const { return _data.is_null(); }
 
private:
   ssc::counted_ptr<base_data> _data;
};
 
 
std::vector<variant> v;
   v.push_back(2.3);
   v.push_back(std::string("hello!"));
   v.push_back(1);
 
 
   std::cout << v[0].get<double>() << std::endl;
   std::cout << v[1].get<std::string>() << std::endl;
   std::cout << v[2].get<int>() << std::endl;
 


Да, counted_ptr можно заменить на std::shared_ptr
« Последнее редактирование: Март 26, 2012, 23:04 от m_ax » Записан

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

Arch Linux Plasma 5
BRE
Гость
« Ответ #58 : Март 26, 2012, 23:18 »

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

Мы напрасно ушли от обсуждения задачи к реализации чуто-контейнера, а если вернутся, то можно предложить такой вариант.
Вот код Igors:
Код:
if (model.mSpaceUV) {   // UV имеются?
 // крутим UV
}

А что значит крутим? Давайте тогда сделаем метод spin, который будет этим заниматься и возвращать результат. Тогда для кручения, клиентам этого объекта, будет не нужно знать как, кто, в чем храниться.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #59 : Март 27, 2012, 00:55 »

variant не очень хорош как раз с точки зрения контроля типов во время компиляции. Мое мнение, чем реже ты скатываешься к варианту, тем лучше. Подмигивающий
Тот редкий случай когда Вы и я согласны Улыбающийся Да, "вариант" - это уже на самый пожарный случай.

А что значит крутим? Давайте тогда сделаем метод spin, который будет этим заниматься и возвращать результат. Тогда для кручения, клиентам этого объекта, будет не нужно знать как, кто, в чем храниться.
Клиент может прекрасно жить не зная ненужных (ему) подробностей, напр (упрощенно)
Код
C++ (Qt)
if (model.mSpaceUV) {
mSpaceUV->SetPoinr3F(0, (mSpaceUV->GetPoint3F(0) + mSpaceUV->GetPoint3F(1)) * 0.5);
}
 
Клиенту в принципе-то нужно немного: Get/Set, и др стандартные операции с контейнером. Да, будут какие-то расходы на возврат по значению, на возможный перевод float <-> double, но они вполне приемлемы

Ну если вы не знаете, я то от куда знаю?
Виноват, немного подгрузил спецификой. Но в конце-концов (с точки зрения чисто программирования) почему мы должны рассматривать/планировать класс только с одним "таким членом"? А если "таких" будет 2 и больше? (как оно и есть)

Но мне лично, идея наследоваться от какого то базового класса, переопределять вирт. функции для каждого типа точек и т.д. правильным путём не кажется(
Всем нам что-то нравится или нет. Но как лучше? Вариант с "вариантом" уже обсуждался, он здесь просто неуместен, т.к. (возможно) миллионы POD точек не должны превратиться в что-то "умное" - они должны остаться столь же "тупыми" как они были созданы

Вообще объясните мне пожалуйста - ну откуда такой "полный минор"? Да, мы видим что ни один стандартный паттерн здесь не годится (насколько я знаю). Так что, обосраться и не жить, что ли? Есть довольно очевидное решение с базовым виртуальным классом (которое я и реализовал). Почему это "костыль", "велосипед", "вилы/грабли", тем более "против логики языка"? Только потому что так не писал Александреску (или кто-то еще)? Что же такого плохого мы делаем? Используем виртуальный механизм? Наследуемся template классом от non-template? И что с того, чем оно плохо?

Есть лучшие задумки (с точки зрения связки/взаимодействия классов) - с удовольствием приму участие в обсуждении. По поводу Append - ну я его маленько раскрутил, там не все так мрачно. Но я никогда не любил ни template ни теорию вообще, поэтому, честно говоря, я (немного) надеялся увидеть лучшие решения от Вас
Записан
Страниц: 1 2 3 [4] 5 6   Вверх
  Печать  
 
Перейти в:  


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