Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 2 [3] 4 5 6   Вниз
  Печать  
Автор Тема: борьба с шаблонами  (Прочитано 132136 раз)
0 Пользователей и 35 Гостей смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #60 : 11-04-2009 17:58 » 

а ещё один глупый вопрос Улыбаюсь

Скажем, я реализую некую работу с
1) массивом элементов T
2) массивом указателей на элемент T

шаблоны вышли одинаковыми, разница лишь T и T* и в доступе к методам элемента:

Код:
//работа с массивом элементов T
template<T>
void WorkWithArrayOfT(T* Array, DWORD dwdCount)
{
   ...
   //доступ к методу T
   Array[0].Method();
   ...
}

//работа с массивом указателей на элементы T
template<T>
void WorkWithArrayOfPointersToT(T** Array, DWORD dwdCount)
{
   ...
   //доступ к методу T
   Array[0]->Method();
   ...
}

то есть к чему я веду ? По сути, если бы не разница в доступе, то строчка

WorkWithArrayOfPointersToT<int>(...,...);

равносильна
WorkWithArrayOfT<int*>(...,...);

И вопрос: как в шаблоне сделать условный выбор оператора доступа ? Тогда оба шаблона с практически идентичным кодом можно было бы держать в одном единственном шаблоне
« Последнее редактирование: 11-04-2009 18:02 от Алексей1153++ » Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #61 : 11-04-2009 18:08 » 

Эммм... в самом общем случае никак, и дело не в шаблоне, а в С++. Поэтому и существуют перегруженные конструкторы и ф-ции, которые работают с указателями и с копиями.
Посему и с шаблонами ты явно указываешь либо это шаблон для типа, либо на указатель типа.

А зачем тебе это надо?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #62 : 11-04-2009 18:17 » 

Цитата
и дело не в шаблоне, а в С++.

на ум пришло только такое опасное решение Улыбаюсь

Код:
template<T,const bool bPointer>
void WorkWithArrayOfT(T* Array, DWORD dwdCount)
{
   ...
   //доступ к методу T
   if(!bPointer)
   {
      ((T*)&Array[0])->Method();
   }
   else
   {
      ((T**)&Array[0])->Method();
   }
   ...
}

Цитата
А зачем тебе это надо?
я же написал зачем - длинный код получился одинаковый, различие только в одной строчке с оператором доступа
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #63 : 11-04-2009 18:48 » 

Джон, Cушествует способ. Классика А. Александреску "Современное проектирование на С++"
Код:
  template <typename U>
      struct PointerTraits
      {
         typedef U* ParametrType;
      };
      template <typename U>
      struct PointerTraits<U*>
      {
         typedef U ParametrType;
      };


     template <typename T>
         class SomeClass
         {
            typedef typename PointerTraits<T>::ParametrType PointerType
            PointerType SomeValue;
         };
SomeValue всегда будет указателем на данные, вне зависимости, что указали при конкретизации шаблона.

Леш, этот пример можно адаптировать под твои нужды.
« Последнее редактирование: 11-04-2009 18:50 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #64 : 11-04-2009 19:00 » 

Finch, как-то это всё сложно для понимания , мозг разбегается ))  Что тут чего делает ?
« Последнее редактирование: 11-04-2009 19:04 от Алексей1153++ » Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #65 : 11-04-2009 19:05 » 

Ничего сложного
Код:
  template <typename U>
      struct PointerTraits
      {
         typedef U* ParametrType;
      };
это обший случай который компилятор обычно будет выбирать, когда будет строить программу.
Код:
      template <typename U>
      struct PointerTraits<U*>
      {
         typedef U ParametrType;
      };
Это конкретизация для указателя, компилятор ее будет выбирать, если встретит указатель на элемент.
Теперь пользуемся этой возможностью
Код:
            typedef typename PointerTraits<T>::ParametrType PointerType
            PointerType SomeValue;

Более полно и конкретно описано в вышеприведденой книге.

« Последнее редактирование: 11-04-2009 19:07 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #66 : 11-04-2009 19:11 » 

PointerType имеет тип "typename PointerTraits<T>::ParametrType"

Код:
template<PointerType,const bool bPointer>
void WorkWithArrayOfT(PointerType* Array, DWORD dwdCount)
{
   ...
   //доступ к методу PointerType
   Array[0]->Method();
}

так ?
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #67 : 11-04-2009 19:14 » 

Неа. Улыбаюсь
Код:
template<typename T>
void WorkWithArrayOfT(PointerType* Array, DWORD dwdCount)
{
   typedef typename PointerTraits<T>::ParametrType PointerType
   PointerType Array;
   //доступ к методу PointerType
   Array[0]->Method();
}
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #68 : 11-04-2009 19:17 » 

Вру, сейчас подправлю код.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #69 : 11-04-2009 19:19 » 

кстати, на это
Код:
  template <typename U>
  struct PointerTraits
  {
     typedef U* ParametrType;
  };
  template <typename U>
  struct PointerTraits<U*>
  {
     typedef U ParametrType;
  };

происходит ругань
error C2989: 'PointerTraits<class ?? ::U *>' : template class has already been defined as a non-template class
error C2988: unrecognizable template declaration/definition
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #70 : 11-04-2009 19:27 » 

А ну все, Это вошло в стандарт помоему в 99 году. Так что естественно VC6 показывает язык. У меня на g++ такое проходит и на ура.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #71 : 11-04-2009 19:29 » 

понятненько ) Тогда оставлю изврат с bool bPointer
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #72 : 11-04-2009 19:29 » 

Код:
template<typename ItemType_>
void WorkWithArrayOfT(ItemType_* Array, DWORD dwdCount)
{
   ...
   //доступ к методу T
   ( (ItemType_*)&Array[0] )->Method();
   ...
}
или нет... И компилятора под рукой нет...
Ещё есть идея с порождением вспомогательного объекта с перекрытым оператором -> (типа умных указателей) Улыбаюсь
« Последнее редактирование: 11-04-2009 19:31 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #73 : 11-04-2009 19:34 » 

Вад, агась, я уже так и поступил. Компилятор пропускает (пост #62)

перегружать оператор неохота, если честно
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #74 : 11-04-2009 19:41 » 

Лёш, на самом деле всё гораздо проще. Для сокращения кода и существует перегрузка ф-ций:

Код:

template <class T> void MyFunction(T obj)
{
...
obj.MyClassMethod();
...
}

template <class T> void MyFunction(T *pObj)
{
T obj = *pObj;
MyFunction(obj);
}

Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #75 : 11-04-2009 20:28 » 

Джон, не могу понять, чем это мне здесь поможет...
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #76 : 11-04-2009 20:33 » 

Тем, что ты напишешь тело БОЛЬШОЙ ф-ции только один раз. Чего ты и добивался.

Цитата
А зачем тебе это надо?
я же написал зачем - длинный код получился одинаковый, различие только в одной строчке с оператором доступа


зы Ну и ессно тем, что это безопасный код без всяких извращений.
« Последнее редактирование: 11-04-2009 20:35 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #77 : 11-04-2009 20:39 » 

Джон, Cушествует способ.

Вить, ща только просмотрел твой код, ИМХО это не то, что спрашивалось. Можешь показать пример использования с объектом и с указателем?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #78 : 11-04-2009 20:43 » 

Сейчас помудрю. Кстати, твой код тоже не будет работать Улыбаюсь У него там не просто один указатель, а массив указателей.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #79 : 11-04-2009 20:52 » 

Легко будет работать, надо только определить оператор = для данного типа. Если же передаётся массив указателей, то просто сделать копию с него, размер-то известен.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #80 : 11-04-2009 21:03 » 

Код:
class MyClass
{
public:

MyClass() {}
void MyClassMethod()
{
int i=3;
printf("Class 1: i=%d\n", i);
}
};

class MyClass2
{
public:

MyClass2() {}
void MyClassMethod()
{
int i=3;
printf("Class 2: i=%d\n", i);
}
};

// основная ф-я с БОЛЬШИМ кодом
template <class T> void MyFunction(T *pObj, int nSize)
{
for(int i=0; i<nSize; i++)
{
pObj[i].MyClassMethod();
}
}

// перегруженая с массивом указателей
template <class T> void MyFunction(T **ppObj, int nSize)
{
T *pObj = new T[nSize];
memcpy(pObj, &ppObj, nSize);
MyFunction(pObj, nSize); // вызов БОЛЬШОЙ ф-ции
}

int main()
{
        // для массива объектов
MyClass2 obj[2];
MyFunction(obj, 2);

        // для массива указателей
MyClass *pObj[2];
pObj[0] = new MyClass();
pObj[1] = new MyClass();

MyFunction((MyClass*)pObj, 2);

delete pObj[0];
delete pObj[1];

return 0;
}

В код внесены изменения для совместимости с 6ой студией. см. ниже
« Последнее редактирование: 11-04-2009 21:49 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #81 : 11-04-2009 21:04 » 

Джон, ну покажи пример прямо для поста №1 Улыбаюсь Может, я просто туплю с недосыпа.

Присваивать временной переменной не хочу. Лучше уж с преобразованием из №62 оставлю
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #82 : 11-04-2009 21:06 » 

Вот код, который у меня полностью работает.
Код:
#include <stdio.h>

   template <typename U>
   struct PointerTraits
   {
      static void Method(U &u) {u.Method();};
   };
   template <typename U>
   struct PointerTraits<U*>
   {
      static void Method(U *u) {u->Method();};
   };

   template <typename T>
static void WorkWithArrayOfT(T* Array, int dwdCount)
{
   //доступ к методу PointerType
     PointerTraits<T>::Method(Array[0]);
}

class a
{
public:
   a() {};
   ~a()  {};
   void Method() {printf("class a\n");};
};


int main()
{
   a **A=new a*[10];
   for (int i =0; i<10; i++) A[i] = new a;
   WorkWithArrayOfT<a*>(A, 10);
   a B[10];
   WorkWithArrayOfT<a>(B, 10);
   return 0;
}
« Последнее редактирование: 11-04-2009 21:21 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #83 : 11-04-2009 21:06 » 

Лёщ, а это он и есть...

Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #84 : 11-04-2009 21:09 » 

Код:

// это основная ф-я с полностью реализованым телом

//работа с массивом элементов T
template<T> void WorkWithArrayOfT(T* Array, DWORD dwdCount)
{
   ...
   //доступ к методу T
   Array[0].Method();
   ...
}

//работа с массивом указателей на элементы T
template<T>
void WorkWithArrayOfPointersToT(T** ppArray, DWORD dwdCount)
{
T *pArray = new T[dwdCount];
memcpy(pArray, &ppArray, dwdCount);
MyFunction(pArray, dwdCount); // вызов БОЛЬШОЙ ф-ции
}

Я только имя переменной изменил немного - терпеть ненавижу когда имя переменной на тим смахивает.
« Последнее редактирование: 11-04-2009 21:11 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #85 : 11-04-2009 21:10 » 

Джон у тебя не идет конкретизация шаблона, следовательно ты пример не прогонял через компилятор. Второе, все наши примеры на VC6 скорее всего и не будут работать.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #86 : 11-04-2009 21:12 » 

Вить, поскольку я сделал с ф-ей main и примерами классов, то это значит что я прогнал это через компилятор и всё работает. Но твоя правда - я сделал это в 2003 студии. Ща на шестёрке прогоню.

зы Вить, а конкретизация и не требуется. Поэтому я и сказал, что твоё решение не совсем то, что требуется. У Лёшки типичная перегрузка ф-ции с разными параметрами.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #87 : 11-04-2009 21:19 » 

Да, в 6ой вторая часть не работает. Не может разрешить перегрузку в случае с массивом указателей.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #88 : 11-04-2009 21:25 » 

Да кстати, у тебя зарыта мина замедленного действия Улыбаюсь . Если в классе будут динамические переменные, могут быть некоторые трудноотлавливаемые баги. Если например приложение многопоточное
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #89 : 11-04-2009 21:29 » new

В 6ой версии нужен явный кастинг при вызове

вместо MyFunction(pObj, 2);  ->  MyFunction((MyClass*)pObj, 2);

Так работает.
« Последнее редактирование: 11-04-2009 21:50 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Страниц: 1 2 [3] 4 5 6   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines