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

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

ru
Offline Offline
Пол: Мужской
Кот рыжий


« : 01-06-2005 03:40 » 


Написал функцию шаблон:

template <typename T1, typename T2>
void FillToolTips(T1 ID, T2 szTipText);

template <typename T1, typename T2>
void CParamDlg::FillToolTips(T1 ID, T2 szTipText)
//
//Заполнение тултипов
//
{
for(int i=0; i<sizeof(ID)/sizeof(int); ++i)
     m_ToolTip.AddTool(GetDlgItem(ID[i]), szTipText[i]);
}

Вызываю так:

//Заполняем тултипы
static int ID[] =
        {
IDOK,
IDCANCEL
        };

      static char *szTipText[] =
      {
"Внести изменения и закрыть окно",
"Закрыть окно без учета изменений"
      };

  FillToolTips(ID, szTipText);

Получаю вот что:

error LNK2019: unresolved external symbol "protected: void __thiscall CParamDlg::FillToolTips<int *,char * *>(int *,char * *)" (??$FillToolTips@PAHPAPAD@CParamDlg@@IAEXPAHPAPAD@Z) referenced in function "private: virtual int __thiscall CLayerParamsDlg::OnInitDialog(void)" (?OnInitDialog@CLayerParamsDlg@@EAEHXZ)

Ну и что это еще значит??? :evil:
« Последнее редактирование: 14-04-2006 21:05 от Алексей1153 » Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
michaelprog
Гость
« Ответ #1 : 01-06-2005 05:00 » 


template <typename T1, typename T2>
void FillToolTips(T1 ID, T2 szTipText); //(1)

template <typename T1, typename T2>
void CParamDlg::FillToolTips(T1 ID, T2 szTipText)
{
for(int i=0; i<sizeof(ID)/sizeof(int); ++i)
 m_ToolTip.AddTool(GetDlgItem(ID[i]), szTipText[i]); // (2)
}

Остается только догадываться, что (1) объвлена в классе CParamDlg. (догадался  Ага)
Выражение sizeof(ID)/sizeof(int) по всей видимости должно вычислять "размер массива", однако работать не будет, если вспомнить, как объявлены эти самые массивы, и как они передаются в функцию. Фактически ты вычисляешь отношение "размера указателя" к "размеру int" (и зачем это может быть нужно).
    static int ID[] =
 {
      IDOK,
      IDCANCEL
 };

 static char *szTipText[] =
 {
      "Внести изменения и закрыть окно",
      "Закрыть окно без учета изменений"
 };

    FillToolTips(ID, szTipText); //(3)
как можно видеть, в качетстве аргументов передаются указатель на одномерный массив целых чисел и указатель на двумерны массив char (две строки), что и отражено в сообщении об ошибке.

error LNK2019: unresolved external symbol "protected: void __thiscall CParamDlg::FillToolTips<int *,char * *>(int *,char * *)" (??$FillToolTips@PAHPAPAD@CParamDlg@@IAEXPAHPAPAD@Z) referenced in function "private: virtual int __thiscall CLayerParamsDlg::OnInitDialog(void)" (?OnInitDialog@CLayerParamsDlg@@EAEHXZ)

Думается размер передавать прийдется явно...

Не понял еще вот чего - откуда m_ToolTip в теле функции FillToolTips (см. стр. 2) и с чем его едят?
Не понятно также, почему членфункцию FillToolTips(ID, szTipText); вызываешь не через Объект класса.

И вообще зачем здесь шаблон, если в теле функции ты знаешь, что имеешь дело с int и строкой char'ов.

ЗЫ. нужы сырцы, тогда можно будет предложить решение
« Последнее редактирование: 20-12-2007 19:39 от Алексей1153++ » Записан
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #2 : 01-06-2005 05:11 » 

Я бы не стал заморачиваться если бы имел дело с int* и char* Передаваемые типы int[n] и char[n] поскольку n мне неизвестно сделал функцию в виде шаблона для работы с любым n только этот шаблон не инстанцируется и я хочу знать почему
sizeof(ID)/sizeof(int) как не странно работает поскольку тип у ID не int* а int[n]
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #3 : 01-06-2005 05:13 » 

Тот же самый код но без шаблона который РАБОТАЕТ
     //Определим все подсказки
      static int ID[] =
        {
      IDOK,
      IDCANCEL
        };

      static const char *szTipText[] =
      {
      "Внести изменения и закрыть окно",
      "Закрыть окно без учета изменений"
      };
      
      //Привязка подсказок
        for(int i=0; i<sizeof(ID)/sizeof(int); i++)
         m_ToolTip.AddTool(GetDlgItem(ID), szTipText);
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #4 : 01-06-2005 05:20 » 

Да и вообще какая разница в каком классе объявлена (1)? и тем более какая разница что такое m_ToolTip?
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
michaelprog
Гость
« Ответ #5 : 01-06-2005 05:26 » 

в отношении int [n] я бы согласился, если бы объявление выглядело так:
Код:
static int ID[2] =
        {
      IDOK,
      IDCANCEL
        };
Вопрос на засыпку: разве sizeof(int) в выражении sizeof(ID)/sizeof(int) не говорит о том, что тебе заведомо известно что типом элементов ID является int?

значит ли выражение " n мне неизвестно", что за формирование вызова отвечает клиентский код к формированию которого ты не имеель отношения?

PS. Исходники в студию
Записан
michaelprog
Гость
« Ответ #6 : 01-06-2005 05:33 » 

Да и вообще какая разница в каком классе объявлена (1)? и тем более какая разница что такое m_ToolTip?
Как это?!
Если m_ToolTip глобальная переменна, то возражения принимаются. однако некрасиво  это...

Возможно в том, что  FillToolTips объявлена вне класса, а реализация внутри CParamDlg и зарыта собака.
Цитата
template <typename T1, typename T2>
void CParamDlg::FillToolTips(T1 ID, T2 szTipText)
Записан
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #7 : 01-06-2005 06:33 » 

Извини, но ты по моему не понимаешь о чем речь
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #8 : 01-06-2005 06:37 » 

Вопрос в передаче массива в шаблонную функцию все остальное неважно
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #9 : 01-06-2005 06:41 » 

> Вопрос на засыпку: разве sizeof(int) в выражении sizeof(ID)/sizeof(int) не говорит о том, что тебе заведомо известно что типом элементов ID >является int?

Понимаешь int[2] и например int[3] разные типы
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
npak
Команда клуба

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

« Ответ #10 : 01-06-2005 10:06 » 

USBLexus,

Тело шаблона  CParamDlg::FillToolTips и вызов  FillToolTips(ID, szTipText); находятся в одном файле?  Если нет, то надо поместить в один или вынести тело шаблона в заголовочный файл
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #11 : 01-06-2005 10:12 » 

USBLexus,

Тело шаблона CParamDlg::FillToolTips и вызов FillToolTips(ID, szTipText); находятся в одном файле? Если нет, то надо поместить в один или вынести тело шаблона в заголовочный файл
Нет, не в одном. Ок завтра попробую
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #12 : 01-06-2005 10:13 » 

Класс который вызывает  FillToolTips(ID, szTipText);  наследует этот шаблон от базового класса
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
Джон
просто
Администратор

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

« Ответ #13 : 01-06-2005 11:43 » 

Чёт я не понял? Что ты под "типом" понимаешь?

Понимаешь int[2] и например int[3] разные типы

Это вообще не типы!!! Это массивы объектов типа int!  А ещё проще - это два куска памяти - один размером 8 байт, второй - 12 байт (на 32 разрядных системах).
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"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."
npak
Команда клуба

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

« Ответ #14 : 01-06-2005 14:57 » new

Чёт я не понял? Что ты под "типом" понимаешь?

Понимаешь int[2] и например int[3] разные типы

Это вообще не типы!!! Это массивы объектов типа int!  А ещё проще - это два куска памяти - один размером 8 байт, второй - 12 байт (на 32 разрядных системах).

С точки зрения транслятора с языка Си int[2] и int[3] являются именно типами (array type). См. стандарт языка Си, раздел 6.2.5
Цитата
An array type describes a contiguously allocated nonempty set of objects with a
particular member object type, called the element type. Array types are
characterized by their element type and by the number of elements in the array. An
array type is said to be derived from its element type, and if its element type is T, the
array type is sometimes called ‘‘array of T’’. The construction of an array type from
an element type is called ‘‘array type derivation’’.

Указатели принадлежат совсем к другому виду типов, а именно ссылочным (reference) типам.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #15 : 02-06-2005 06:09 » 

npak 

Да действительно перенес тело шаблона в заголовочный файл и все заработало Спасибо!

Обнаружил такую особенность если передавать массив int[2] в шаблон то он будет инстанцирован как int* а если передавать не сам массив а ссылку на массив int[2]& тогда он правильно инстанцируется с типом int[2] интересно с чем это связано?
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
USBLexus
Опытный

ru
Offline Offline
Пол: Мужской
Кот рыжий


« Ответ #16 : 02-06-2005 06:21 » 

Для массива получается что не вызывается конструктор копирования?
Записан

#define QUESTION(b) (2*b)||(!(2*b)) (c) William Shakespeare
Earnest
Гость
« Ответ #17 : 16-06-2005 16:50 » 

Обнаружил такую особенность если передавать массив int[2] в шаблон то он будет инстанцирован как int* а если передавать не сам массив а ссылку на массив int[2]& тогда он правильно инстанцируется с типом int[2] интересно с чем это связано?
При передаче имени массива на самом деле передается адрес первого элемента - наследие С. А конструктор копирования, конечно, не вызывается. Слава богу.
Записан
NetRaider
Гость
« Ответ #18 : 05-07-2005 04:56 » 

Цитата

Написал функцию шаблон:

template <typename T1, typename T2>
void FillToolTips(T1 ID, T2 szTipText);

template <typename T1, typename T2>
void CParamDlg::FillToolTips(T1 ID, T2 szTipText)
//
//Заполнение тултипов
//
{
   for(int i=0; i<sizeof(ID)/sizeof(int); ++i)
     m_ToolTip.AddTool(GetDlgItem(ID[i]), szTipText[i]);
}

Вызываю так:

   //Заполняем тултипы
    static int ID[] =
        {
      IDOK,
      IDCANCEL
        };

      static char *szTipText[] =
      {
      "Внести изменения и закрыть окно",
      "Закрыть окно без учета изменений"
      };

     FillToolTips(ID, szTipText);
...


Давай по порядку:

// ID здесь имеет тип int[2]
// А так так в С++ нельзя передавать массивы в ф-ии по значению,
// то применяется 'array-to-pointer' преобразование
FillToolTips(ID, szTipText);


// В результате чего тип T1 в шаблоне будет 'int*'
// и размер массива будет потерян
template <typename T1, typename T2>
void FillToolTips(T1 ID, T2 szTipText);

Для того чтобы в функции можно было узнать размер массива
можно передавать ссылку на массив:
template <typename T1, typename T2>
void FillToolTips(T1& ID, T2 szTipText);

тогда выражение 'sizeof(ID)/sizeof(int)' даст правильный результат

Второй, более правильный вариант - заставить компилятор выводить
размер массива самостоятельно:

template <typename T1, typename T2, size_t N>
void FillToolTips(const T1 (&ID)[N], T2 szTipText)
{}

Значение N будет выведено автоматически (но этот вариант поддерживают не все компиляторы, к числу которых относится VC6).

Цитата
Обнаружил такую особенность если передавать массив int[2] в шаблон то он будет инстанцирован как int* а если передавать не сам массив а ссылку на массив int[2]& тогда он правильно инстанцируется с типом int[2] интересно с чем это связано?

см.выше

--------------------------------
Цитата
Для массива получается что не вызывается конструктор копирования?
Маасивы никогда не передаются по значению и конструкторов копирования не имеют

Цитата
При передаче имени массива на самом деле передается адрес первого элемента - наследие С.

Это не всегода верно. Что передаеться, на самом деле зависит от типа параметра функции.
Выше я обяъснял, что может передаваться как указатель на первый элемент, так и ссылка на массив.
« Последнее редактирование: 20-12-2007 19:42 от Алексей1153++ » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines