На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ANDLL, ALXR
Страницы: (12) 1 2 [3] 4 5 ...  11 12 все  ( Перейти к последнему сообщению )  
> #define ИЛИ template? , C++
   
#define ИЛИ template
Гости не могут просматривать результаты голосования.
Гости не могут голосовать 
    Цитата OpenGL @
    Попробуй ответить на этот вопрос самостоятельно. Тебе для этого надо знать только то, что я не пишу на Си - остальную информацию для ответа ты можешь получить из моих постов этой темы. :D

    Ну то есть никогда. К слову - когда я писал на Си, после С++ - да было больно, с непревычки, но и там - я как то обходился без goto. А значит такие "паттерны" просто говорят о том, что автору было лень придумывать что то другое и умное(ну бывает такое), либо он обычный быдлокодер, пишет на отвали.

    Цитата OpenGL @
    Киля, перечитай внимательней. Простейший паттерн:
    1) сложная инициализация локальных переменных
    2) главные действия, которые могут прерваться из разных мест, после чего надо перейти в 3)
    3) очистка того, что создали в 1)

    Ты сейчас просто сформулировал некий алгоритм, куда наложил некие ограничение, из которых как то следует, что самый простой способ реализовать именно этот алгоритм, путем использования goto. Но ведь у тебя не возникает ведь такой алгоритм на том языке на которым ты пишешь? Что, в Си нет средств обойти это без использования goto ? Хорошо, пусть бьет каждую сущность на отдельные функции какие то, блоки. Вот я беру пример с МСДНа с кучкой goto, это при том, что он тамписан на С++, т.к. юзаются классы/COM/еще какая нибудь фигня, и переписываю это все без goto. Вы же сейчас или специально или я не пойму, выдумываете какие то ограничения, которыми в реальной жизни вы не ограничены.

    Добавлено
    Цитата OpenGL @
    твоим паттерном do..while более читабельным не сделать, если в 2 у тебя есть циклы, из которых ты можешь выходить сразу в 3)

    Так в данном случае намеренно усложняется задача. Т.е. вместо того, чтобы посидеть подумать как всего этого избежать, и сделать код более удобочитаемым и расширяемым, вы решили юзать goto.

    А что ты будешь делать(ну или Qraizer, cppasm, кто там еще топил? Fester) если дальше добавятся еще 10 вложенных циклов, и из каждого при определенном условии нужно выпрыгнуть на очистку ресурсов? Я так полагаю вы будете заводить 10 разный меток, и прыгать? Да? Судя по всему да. Отличный подход, и во что превратится этот код? Это будет все еще паттерн?

    Цитата OpenGL @
    Ну и до кучи могу напомнить эту тему - в ней был пример, когда с помощью goto вообще заходят внутрь тройного цикла, и более читабельный вариант того примера, но без goto, никто, включая тебя, так и не родил.

    А пример найти можешь? Я помню там Qraizer его приводил, но я не помню смысл примера. Если на пример не накладываются ограничения - значит это исключительная ситуация. И ты сам прекрасно должен понимать, что запрыгивание внутрь тройного цикла - больше смахивает на какой то грязный хак или даже костыль в перемешку с говнокодом, чем на паттерн или обычный подход в программировании. Так что с этим примером так же мимо я думаю. Искать мне его лень.
      Цитата KILLER @
      К слову - когда я писал на Си, после С++ - да было больно, с непревычки, но и там - я как то обходился без goto. А значит такие "паттерны" просто говорят о том, что автору было лень придумывать что то другое и умное(ну бывает такое), либо он обычный быдлокодер, пишет на отвали.

      Когда я писал на Си - тоже не возникало. Вот только писал я на нём программы в сотню-другую строк максимум. Если же заглянуть в любой крупный проект на нём (например,вот тебе первый попавшийся файл из nginx-а), то goto там - сплошь и рядом, и при этом куда переходит выполнение кода - прекрасно видно.

      Цитата KILLER @
      Но ведь у тебя не возникает ведь такой алгоритм на том языке на которым ты пишешь?

      Такой алгоритм? Возникает постоянно, но см. выше - на си я не пишу, поэтому данный случай прекрасно разрруливается другими средствами.

      Цитата KILLER @
      Что, в Си нет средств обойти это без использования goto ?

      Раз он там используется повсеместно - видимо, нет :-?

      Цитата KILLER @
      А пример найти можешь?

      Я уже тему нашёл. Если тебе лень перечитывать 18 страниц, то мне тем более лень это делать :D Суть примера простая - есть тройной цикл со сложной логикой счётчиков (не просто for i,j,k = 0..n), он длинный, поэтому его можно прерывать. Но если он прервался - надо прочитать значения счётчиков, на которых мы остановились, после чего как ни в чём не бывало зайти внутрь циклов - всё просто и понятно. Структурный вариант в той теме был, но с goto он мог соревноваться только с краткостью записи, но никак не с понятностью (там сложная логика в условиях выхода из циклов, и неочевидный инкремент были).
        Цитата
        А что ты будешь делать(ну или Qraizer, cppasm, кто там еще топил? Fester) если...

        Я тебе уже много раз говорил, что если использование goto делает код более понятным, то момно и нужно использовать goto. Если ты дописываешь какие-то конструкции только ради того, чтобы избавиться от goto, то ты пишешь говнокод.
          Цитата KILLER @
          Я так полагаю вы будете заводить 10 разный меток, и прыгать? Да?

          Нет. У меня деструкторы есть для этого. И зачем 10 меток? Метка очистки обычно одна. Если их нужно больше, то я, если бы писал на си, подумал бы об упрощении, наверное.
            Цитата OpenGL @
            Вот только писал я на нём программы в сотню-другую строк максимум. Если же заглянуть в любой крупный проект на нём (например,вот тебе первый попавшийся файл из nginx-а), то goto там - сплошь и рядом, и при этом куда переходит выполнение кода - прекрасно видно.

            То есть если это файл из nginx - значит там автоматом не может быть говнокода? Я его начал мотать по твоей ссылке, не выдержал нажал поиск, первый же встретившийся goto - посмотри на саму функцию, ее по хорошему уже можно было только разбить на 3-4 функций. Зачем такие большие функции писать? Может быть от этого и юзают там goto? Кто то пишет крупные проекты в одной функции main, и считает что это норма. Я видел функцию длинной в 5 тысяч строк кода. Это что нормально? Если бы автор перепроектировал свой код, думаю можно было сделать его более удобочитаемым.
            Сам файл 5 тыс строк кода. Это нормально? Ты так же бы это все написал? В таком стиле? Я не знаю, я не курил этот код, но думается мне, возможно один этот *.с файл превратился в 10 файлов или даже в подпроект. Я лично считаю это плохим подходом, когда у тебя файл в 5 тыс строк, там же черт ногу сломит. Потому что такой код потом сопровождать очень сложно. Если это автор писал для себя, и будет сам лично его сопровождать, то я тут спорить не буду, пусть хоть все 5 тыс строк кода пишет на одних goto в одной функции. Его право.

            Цитата OpenGL @
            Такой алгоритм? Возникает постоянно, но см. выше - на си я не пишу, поэтому данный случай прекрасно разрруливается другими средствами.

            Тот, который ты придумал. Ну вот выше я переписал код cppasm, там похожая проблема. Мне мой подход нравится больше. При этом я вроде переписал в С стиле, не прибегая к средствам С++. Что я сделал не так?
            Может вы сейчас придеретесь к количеству строчек? Типа у него 10, а у меня 20 ?

            Цитата OpenGL @
            Раз он там используется повсеместно - видимо, нет :-?

            Где там? В С? Нет, не повсеместно. Но, изначально речь зашла про майкрософт, а у них не только в Си коде goto, открой ATL/MFC исходники посмотри. Что используя С++ нельзя обойтись без goto?

            Цитата OpenGL @
            Я уже тему нашёл. Если тебе лень перечитывать 18 страниц, то мне тем более лень это делать :D Суть примера простая - есть тройной цикл со сложной логикой счётчиков (не просто for i,j,k = 0..n), он длинный, поэтому его можно прерывать. Но если он прервался - надо прочитать значения счётчиков, на которых мы остановились, после чего как ни в чём не бывало зайти внутрь циклов - всё просто и понятно. Структурный вариант в той теме был, но с goto он мог соревноваться только с краткостью записи, но никак не с понятностью (там сложная логика в условиях выхода из циклов, и неочевидный инкремент были).

            Понимаешь, лично я не ограничен каким либо одним средством и костылем. Возможно задачу стоило переписать на другом языке, возможно стоило вообще по другому ее сформулировать и решать совершенно с другим подходом. Там лишь обсуждалась, на сколько я помню, конкретная реализация, которую предлагалось переписать без goto. но ведь так можно написать абсолютно любой грязный хак, сказать вот есть вот именно вот такое условие - на перепиши без грязного хака. И ты скажешь - да, при такой постановке задачи, и при таких условиях - это решается только грязным хаком. Но это ведь не означает, что это единственно верное решение задачи в целом?

            Цитата Fester @
            Я тебе уже много раз говорил, что если использование goto делает код более понятным, то момно и нужно использовать goto

            Так приведи мне хоть один пример, когда goto делает код более понятным?

            Цитата OpenGL @
            Нет. У меня деструкторы есть для этого. И зачем 10 меток?

            Ну как зачем. Разные условия потому что, разное поведение должно быть в разных подциклах. Можно ведь сформулировать задачу по разному, и ты скажешь - а что вообще требуется? И почему задача сформулирована именно вот так, а не вот эдак. И ты будешь абсолютно прав. И вот это я вам и пишу, а вы рассказываете о каких то мифических вещах, приводя условяи с ограничениями. Вот есть вот у меня 5 вложенных циклов с тремя goto - перепеши чтоб 5 вложенных циклов осталось ,а goto исчез. А зачем так делать? Может быть проще вообще каждый подцикл вынести в отдельную функцию? Почему я должен переписывать именно вот так, а не кардинально менять алгоритм? Я вот это не понимаю.

            Добавлено
            К слову, вот пост https://forum.sources.ru/next/index.php?sho...dpost&p=3190250 Qraizer
            Вот код:
            ExpandedWrap disabled
              #include <windows.h>
              #include <io.h>
              #include <conio.h>
              #include <fstream>
              #include <iostream>
               
              int main()
              {
               int i, j, k, l;
               
               if (_access("savedstate.dat", 4) == 0)     // Проверить, нет ли сохранённого состояния от предыдущего запуска
               {                                             // Если есть, восстановить и продолжиться
                 std::ifstream inFile("savedstate.dat");
                 bool          ok = true;
               
                 ok = ok && inFile.read(reinterpret_cast<char*>(&i), sizeof(i)).gcount() == sizeof(i);
                 ok = ok && inFile.read(reinterpret_cast<char*>(&j), sizeof(j)).gcount() == sizeof(j);
                 ok = ok && inFile.read(reinterpret_cast<char*>(&k), sizeof(k)).gcount() == sizeof(k);
                 ok = ok && inFile.read(reinterpret_cast<char*>(&l), sizeof(l)).gcount() == sizeof(l);
                 if (ok && (inFile.good() || inFile.eof()))
                 {
                   std::cout << "The saved state is successfully restored." << std::endl;
                   goto resume;
                 }
                 else return std::cerr << "The saved state restoring error. State file is wrong." << std::endl,
                             1;
               }
               
               for (i=0; i<10; ++i)
               {
                 for (j=i; j<10; ++j)
                 {
                   for (k=j; k<10; ++k)
                   {
                     for (l=k; l<10; ++l)
                     {
              resume:
                       if (kbhit() && getch() == '\x1B')     // Проверить, не просят ли нас ESCпом прерваться
                       {                                     // Если да, сохранить состояние и выйти
                         if (_access("savedstate.dat", 2) == 0) remove("savedstate.dat");
                      
                         std::ofstream outFile("savedstate.dat");
                         bool ok = true;
                      
                         ok = ok && outFile.write(reinterpret_cast<char*>(&i), sizeof(i)).good();
                         ok = ok && outFile.write(reinterpret_cast<char*>(&j), sizeof(j)).good();
                         ok = ok && outFile.write(reinterpret_cast<char*>(&k), sizeof(k)).good();
                         ok = ok && outFile.write(reinterpret_cast<char*>(&l), sizeof(l)).good();
                         if (!(ok && (outFile.good() || outFile.eof())))
                           return std::cerr << "The state saving error." << std::endl,
                                 1;
                         return std::cout << "The state successfully saved." << std::endl,
                                2;
                       }
               
                       /* ... */
               
                       std::cout << "i = " << i << ", j = " << j << ", k = " << k << ", l = " << l << std::endl;
                       Sleep(1);
                     }
                   }
                 }
               }
               
               if (_access("savedstate.dat", 2) == 0) remove("savedstate.dat");
               return 0;
              }

            Действительно, что тут не понятного. Без goto переписать ну просто не реально. :ph34r:

            Добавлено
            Причем это не Сишный код, а самый что ни на есть С++сный.

            Добавлено
            Прод код майкрософта из atlmfc:
            ExpandedWrap disabled
              inline HRESULT CSecurityDescriptor::SetPrivilege(
                  _In_z_ LPCTSTR privilege,
                  _In_ BOOL bEnable,
                  _In_ HANDLE hToken)
              {
                  TOKEN_PRIVILEGES tpPrevious;
                  TOKEN_PRIVILEGES tp;
                  DWORD  cbPrevious = sizeof(TOKEN_PRIVILEGES);
                  LUID   luid;
                  HANDLE hTokenUsed;
               
                  if (!LookupPrivilegeValue(NULL, privilege, &luid ))
                      goto _Error;
               
                  // if no token specified open process token
                  if (hToken != 0)
                      hTokenUsed = hToken;
                  else
                      if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenUsed))
                          goto _Error;
               
                  tp.PrivilegeCount = 1;
                  tp.Privileges[0].Luid = luid;
                  tp.Privileges[0].Attributes = 0;
               
                  memset(&tpPrevious, 0, sizeof(tpPrevious));
               
                  if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious))
                      goto _Error_CloseHandle;
               
                  tpPrevious.PrivilegeCount = 1;
                  tpPrevious.Privileges[0].Luid = luid;
               
                  if (bEnable)
                      tpPrevious.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED;
                  else
                      tpPrevious.Privileges[0].Attributes &= ~SE_PRIVILEGE_ENABLED;
               
                  if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tpPrevious, cbPrevious, NULL, NULL))
                      goto _Error_CloseHandle;
               
                  if(hToken == 0)
                      CloseHandle(hTokenUsed);
               
                  return S_OK;
               
                  HRESULT hr;
               
              _Error:
                  hr = AtlHresultFromLastError();
                  return hr;
               
              _Error_CloseHandle:
                  hr = AtlHresultFromLastError();
                  if (hToken == 0)
                      CloseHandle(hTokenUsed);
                  return hr;
              }


            Еще один продакшн код майкрософта из atlmfc
            ExpandedWrap disabled
                  inline BOOL Parse(_In_z_ LPCTSTR lpszUrl)
                  {
                      ATLENSURE(lpszUrl != NULL);
               
                      TCHAR ch;
                      BOOL bGotScheme = FALSE;
                      BOOL bGotUserName = FALSE;
                      BOOL bGotHostName = FALSE;
                      BOOL bGotPortNumber = FALSE;
                      CAtlString strCurrentUrl;
                      TCHAR* szCurrentUrl = strCurrentUrl.GetBuffer(ATL_URL_MAX_URL_LENGTH+6);
                      TCHAR* pszCurrentUrl = szCurrentUrl;
                      size_t nUrlSize = 0;
               
                      BOOL bInsideSquareBrackets = FALSE;
               
                      //parse lpszUrl using szCurrentUrl to store temporary data
               
                      //this loop will get the following if it exists:
                      //<protocol>://user:pass@server:port
                      while ((ch = *lpszUrl) != '\0')
                      {
                          if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+5)
                              goto error;
               
                          if (ch == ':' && !bInsideSquareBrackets)
                          {
                              //3 cases:
                              //(1) Just encountered a scheme
                              //(2) Port number follows
                              //(3) Form of username:password@
               
                              // Check to see if we've just encountered a scheme
                              *pszCurrentUrl = '\0';
                              if (!bGotScheme)
                              {
                                  if (!SetSchemeName(szCurrentUrl))
                                      goto error;
               
                                  //Set a flag to avoid checking for
                                  //schemes everytime we encounter a :
                                  bGotScheme = TRUE;
               
                                  if (*(lpszUrl+1) == '/')
                                  {
                                      if (*(lpszUrl+2) == '/')
                                      {
                                          //the mailto scheme cannot have a '/' following the "mailto:" portion
                                          if (bGotScheme && m_nScheme == ATL_URL_SCHEME_MAILTO)
                                              goto error;
               
                                          //Skip these characters and continue
                                          lpszUrl+= 2;
                                      }
                                      else
                                      {
                                          //it is an absolute path
                                          //no domain name, port, username, or password is allowed in this case
                                          //break to loop that gets path
                                          lpszUrl++;
                                          pszCurrentUrl = szCurrentUrl;
                                          nUrlSize = 0;
                                          break;
                                      }
                                  }
               
                                  //reset pszCurrentUrl
                                  pszCurrentUrl = szCurrentUrl;
                                  nUrlSize = 0;
                                  lpszUrl++;
               
                                  //if the scheme is file, skip to getting the path information
                                  if (m_nScheme == ATL_URL_SCHEME_FILE)
                                      break;
                                  continue;
                              }
                              else if (!bGotUserName || !bGotPortNumber)
                              {
                                  //It must be a username:password or a port number
                                  *pszCurrentUrl = '\0';
               
                                  pszCurrentUrl = szCurrentUrl;
                                  nUrlSize = 0;
                                  TCHAR tmpBuf[ATL_URL_MAX_PASSWORD_LENGTH+1];
                                  TCHAR* pTmpBuf = tmpBuf;
                                  int nCnt = 0;
               
                                  //get the user or portnumber (break on either '/', '@', or '\0'
                                  while (((ch = *(++lpszUrl)) != '/') && (ch != '@') && (ch != '\0'))
                                  {
                                      if (nCnt >= ATL_URL_MAX_PASSWORD_LENGTH)
                                          goto error;
               
                                      *pTmpBuf++ = ch;
                                      nCnt++;
                                  }
                                  *pTmpBuf = '\0';
               
                                  //if we broke on a '/' or a '\0', it must be a port number
                                  if (!bGotPortNumber && (ch == '/' || ch == '\0'))
                                  {
                                      //the host name must immediately preced the port number
                                      if (!SetHostName(szCurrentUrl))
                                          goto error;
               
                                      //get the port number
                                      m_nPortNumber = (ATL_URL_PORT) _ttoi(tmpBuf);
               
                                      bGotPortNumber = bGotHostName = TRUE;
                                  }
                                  else if (!bGotUserName && ch=='@')
                                  {
                                      //otherwise it must be a username:password
                                      if (!SetUserName(szCurrentUrl) || !SetPassword(tmpBuf))
                                          goto error;
               
                                      bGotUserName = TRUE;
                                      lpszUrl++;
                                  }
                                  else
                                  {
                                      goto error;
                                  }
                              }
                          }
                          else if (ch == '@')
                          {
                              if (bGotUserName)
                                  goto error;
               
                              //type is userinfo@
                              *pszCurrentUrl = '\0';
                              if (!SetUserName(szCurrentUrl))
                                  goto error;
               
                              bInsideSquareBrackets = FALSE;
               
                              bGotUserName = TRUE;
                              lpszUrl++;
                              pszCurrentUrl = szCurrentUrl;
                              nUrlSize = 0;
                          }
                          else if (ch == '/' || ch == '?' || (!*(lpszUrl+1)))
                          {
                              //we're at the end of this loop
                              //set the domain name and break
                              if (!*(lpszUrl+1) && ch != '/' && ch != '?')
                              {
                                  if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+4)
                                      goto error;
               
                                  *pszCurrentUrl++ = ch;
                                  nUrlSize++;
                                  lpszUrl++;
                              }
                              *pszCurrentUrl = '\0';
                              if (!bGotHostName)
                              {
                                  if (!SetHostName(szCurrentUrl))
                                      goto error;
                              }
                              pszCurrentUrl = szCurrentUrl;
                              nUrlSize = 0;
                              break;
                          }
                          else
                          {
                              if (ch == '[' && bGotScheme && !bGotHostName)
                                  bInsideSquareBrackets = TRUE;
                              else if (ch == ']')
                                  bInsideSquareBrackets = FALSE;
               
                              *pszCurrentUrl++ = ch;
                              lpszUrl++;
                              nUrlSize++;
                          }
                      }
               
                      if (!bGotScheme)
                          goto error;
               
                      //Now build the path
                      while ((ch = *lpszUrl) != '\0')
                      {
                          if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+5)
                              goto error;
               
                          //break on a '#' or a '?', which delimit "extra information"
                          if (m_nScheme != ATL_URL_SCHEME_FILE && (ch == '#' || ch == '?'))
                          {
                              break;
                          }
                          *pszCurrentUrl++ = ch;
                          nUrlSize++;
                          lpszUrl++;
                      }
                      *pszCurrentUrl = '\0';
               
                      if (*szCurrentUrl != '\0' && !SetUrlPath(szCurrentUrl))
                          goto error;
               
                      pszCurrentUrl = szCurrentUrl;
                      nUrlSize = 0;
               
                      while ((ch = *lpszUrl++) != '\0')
                      {
                          if (nUrlSize >= ATL_URL_MAX_URL_LENGTH+5)
                              goto error;
               
                          *pszCurrentUrl++ = ch;
                          nUrlSize++;
                      }
               
                      *pszCurrentUrl = '\0';
                      if (*szCurrentUrl != '\0' && !SetExtraInfo(szCurrentUrl))
                          goto error;
               
                      switch(m_nScheme)
                      {
                          case ATL_URL_SCHEME_FILE:
                              m_nPortNumber = ATL_URL_INVALID_PORT_NUMBER;
                              break;
                          case ATL_URL_SCHEME_NEWS:
                              m_nPortNumber = ATL_URL_INVALID_PORT_NUMBER;
                              break;
                          case ATL_URL_SCHEME_MAILTO:
                              m_nPortNumber = ATL_URL_INVALID_PORT_NUMBER;
                              break;
                          default:
                              if (!bGotPortNumber)
                                  m_nPortNumber = (unsigned short)AtlGetDefaultUrlPort(m_nScheme);
                      }
               
                      return TRUE;
               
              error:
                      InitFields();
                      return FALSE;
               
                  }

            Ну конечно, это ведь все писалось в 80-ые года, когда кроме goto никто ничего не знал. Ну и для обратной совместимости осталось.

            Это продакшн код!!! Не примеры, не SDK и не MSDN, если вы мне не верите, посмотрите у себя.
            Конечно, как тут без goto переписать то по другому? Ну просто нереально сложно. Проще ведь goto впихнуть.


            А это! Это просто шедевр!!! cppasm, помнишь обвинял меня в том, что я бла бла бла, просто вчера я был реально занят, и не было у меня времени смотреть, а вот сейчас нашел немножко времени.
            Оцени, бла бла бла:
            ExpandedWrap disabled
              BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
              {
                  LRESULT lResult = 0;
                  union MessageMapFunctions mmf;
                  mmf.pfn = 0;
                  CInternalGlobalLock winMsgLock;
                  // special case for commands
                  if (message == WM_COMMAND)
                  {
                      if (OnCommand(wParam, lParam))
                      {
                          lResult = 1;
                          goto LReturnTrue;
                      }
                      return FALSE;
                  }
               
                  if (message == WM_CREATE && m_pDynamicLayout != NULL)
                  {
                      ASSERT_VALID(m_pDynamicLayout);
               
                      if (!m_pDynamicLayout->Create(this))
                      {
                          delete m_pDynamicLayout;
                          m_pDynamicLayout = NULL;
                      }
                      else
                      {
                          InitDynamicLayout();
                      }
                  }
               
                  // special case for notifies
                  if (message == WM_NOTIFY)
                  {
                      NMHDR* pNMHDR = (NMHDR*)lParam;
                      if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
                          goto LReturnTrue;
                      return FALSE;
                  }
               
                  // special case for activation
                  if (message == WM_ACTIVATE)
                      _AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam));
               
                  // special case for set cursor HTERROR
                  if (message == WM_SETCURSOR &&
                      _AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam)))
                  {
                      lResult = 1;
                      goto LReturnTrue;
                  }
               
                 // special case for windows that contain windowless ActiveX controls
                 BOOL bHandled;
               
                 bHandled = FALSE;
                 if ((m_pCtrlCont != NULL) && (m_pCtrlCont->m_nWindowlessControls > 0))
                 {
                    if (((message >= WM_MOUSEFIRST) && (message <= AFX_WM_MOUSELAST)) ||
                       ((message >= WM_KEYFIRST) && (message <= WM_IME_KEYLAST)) ||
                       ((message >= WM_IME_SETCONTEXT) && (message <= WM_IME_KEYUP)))
                    {
                       bHandled = m_pCtrlCont->HandleWindowlessMessage(message, wParam, lParam, &lResult);
                    }
                 }
                 if (bHandled)
                 {
                    goto LReturnTrue;
                 }
               
                  switch (message)
                  {
                  case WM_SIZE:
                      {
                          ResizeDynamicLayout();
               
                          CHwndRenderTarget* pRenderTarget = GetRenderTarget();
                          if (pRenderTarget != NULL && pRenderTarget->IsValid())
                          {
                              pRenderTarget->Resize(CD2DSizeU(UINT32(LOWORD(lParam)), UINT32(HIWORD(lParam))));
                              RedrawWindow();
                          }
                      }
                      break;
               
                  case WM_PAINT:
                      if (DoD2DPaint())
                      {
                          lResult = 1;
                          goto LReturnTrue;
                      }
                      break;
               
                  case WM_ERASEBKGND:
                      if (m_pRenderTarget != NULL && m_pRenderTarget->IsValid())
                      {
                          lResult = 1;
                          goto LReturnTrue;
                      }
                      break;
                  }
               
                  const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();
                  UINT iHash; iHash = (LOWORD((DWORD_PTR)pMessageMap) ^ message) & (iHashMax-1);
                  winMsgLock.Lock(CRIT_WINMSGCACHE);
                  AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash];
                  const AFX_MSGMAP_ENTRY* lpEntry;
                  if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap)
                  {
                      // cache hit
                      lpEntry = pMsgCache->lpEntry;
                      winMsgLock.Unlock();
                      if (lpEntry == NULL)
                          return FALSE;
               
                      // cache hit, and it needs to be handled
                      if (message < 0xC000)
                          goto LDispatch;
                      else
                          goto LDispatchRegistered;
                  }
                  else
                  {
                      // not in cache, look for it
                      pMsgCache->nMsg = message;
                      pMsgCache->pMessageMap = pMessageMap;
               
                      for (/* pMessageMap already init'ed */; pMessageMap->pfnGetBaseMap != NULL;
                          pMessageMap = (*pMessageMap->pfnGetBaseMap)())
                      {
                          // Note: catch not so common but fatal mistake!!
                          //      BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd)
                          ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
                          if (message < 0xC000)
                          {
                              // constant window message
                              if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,
                                  message, 0, 0)) != NULL)
                              {
                                  pMsgCache->lpEntry = lpEntry;
                                  winMsgLock.Unlock();
                                  goto LDispatch;
                              }
                          }
                          else
                          {
                              // registered windows message
                              lpEntry = pMessageMap->lpEntries;
                              while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL)
                              {
                                  UINT* pnID = (UINT*)(lpEntry->nSig);
                                  ASSERT(*pnID >= 0xC000 || *pnID == 0);
                                      // must be successfully registered
                                  if (*pnID == message)
                                  {
                                      pMsgCache->lpEntry = lpEntry;
                                      winMsgLock.Unlock();
                                      goto LDispatchRegistered;
                                  }
                                  lpEntry++;      // keep looking past this one
                              }
                          }
                      }
               
                      pMsgCache->lpEntry = NULL;
                      winMsgLock.Unlock();
                      return FALSE;
                  }
               
              LDispatch:
                  ASSERT(message < 0xC000);
               
                  mmf.pfn = lpEntry->pfn;
               
                  switch (lpEntry->nSig)
                  {
                  default:
                      ASSERT(FALSE);
                      break;
                  case AfxSig_l_p:
                      {
                          CPoint point(lParam);      
                          lResult = (this->*mmf.pfn_l_p)(point);
                          break;
                      }      
                  case AfxSig_b_D_v:
                      lResult = (this->*mmf.pfn_b_D)(CDC::FromHandle(reinterpret_cast<HDC>(wParam)));
                      break;
               
                  case AfxSig_l_D_u:
                      lResult = (this->*mmf.pfn_l_D_u)(CDC::FromHandle(reinterpret_cast<HDC>(wParam)), (UINT)lParam);
                      break;
               
                  case AfxSig_b_b_v:
                      lResult = (this->*mmf.pfn_b_b)(static_cast<BOOL>(wParam));
                      break;
               
                  case AfxSig_b_u_v:
                      lResult = (this->*mmf.pfn_b_u)(static_cast<UINT>(wParam));
                      break;
               
                  case AfxSig_b_h_v:
                      lResult = (this->*mmf.pfn_b_h)(reinterpret_cast<HANDLE>(wParam));
                      break;
               
                  case AfxSig_i_u_v:
                      lResult = (this->*mmf.pfn_i_u)(static_cast<UINT>(wParam));
                      break;
               
                  case AfxSig_C_v_v:
                      lResult = reinterpret_cast<LRESULT>((this->*mmf.pfn_C_v)());
                      break;
               
                  case AfxSig_v_u_W:
                      (this->*mmf.pfn_v_u_W)(static_cast<UINT>(wParam),
                          CWnd::FromHandle(reinterpret_cast<HWND>(lParam)));
                      break;
               
                  case AfxSig_u_u_v:
                      lResult = (this->*mmf.pfn_u_u)(static_cast<UINT>(wParam));
                      break;
               
                  case AfxSig_b_v_v:
                      lResult = (this->*mmf.pfn_b_v)();
                      break;
               
                  case AfxSig_b_W_uu:
                      lResult = (this->*mmf.pfn_b_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
                          LOWORD(lParam), HIWORD(lParam));
                      break;
               
                  case AfxSig_b_W_COPYDATASTRUCT:
                      lResult = (this->*mmf.pfn_b_W_COPYDATASTRUCT)(
                          CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
                          reinterpret_cast<COPYDATASTRUCT*>(lParam));
                      break;
               
                  case AfxSig_b_v_HELPINFO:
                      lResult = (this->*mmf.pfn_b_HELPINFO)(reinterpret_cast<LPHELPINFO>(lParam));
                      break;
               
                  case AfxSig_CTLCOLOR:
                      {
                          // special case for OnCtlColor to avoid too many temporary objects
                          ASSERT(message == WM_CTLCOLOR);
                          AFX_CTLCOLOR* pCtl = reinterpret_cast<AFX_CTLCOLOR*>(lParam);
                          CDC dcTemp;
                          dcTemp.m_hDC = pCtl->hDC;
                          CWnd wndTemp;
                          wndTemp.m_hWnd = pCtl->hWnd;
                          UINT nCtlType = pCtl->nCtlType;
                          // if not coming from a permanent window, use stack temporary
                          CWnd* pWnd = CWnd::FromHandlePermanent(wndTemp.m_hWnd);
                          if (pWnd == NULL)
                          {
                              // determine the site of the OLE control if it is one
                              COleControlSite* pSite;
                              if (m_pCtrlCont != NULL && (pSite = (COleControlSite*)
                                  m_pCtrlCont->m_siteMap.GetValueAt(wndTemp.m_hWnd)) != NULL)
                              {
                                  wndTemp.m_pCtrlSite = pSite;
                              }
               
                              pWnd = &wndTemp;
                          }
                          HBRUSH hbr = (this->*mmf.pfn_B_D_W_u)(&dcTemp, pWnd, nCtlType);
                          // fast detach of temporary objects
                          dcTemp.m_hDC = NULL;
                          wndTemp.m_hWnd = NULL;
                          lResult = reinterpret_cast<LRESULT>(hbr);
                      }
                      break;
               
                  case AfxSig_CTLCOLOR_REFLECT:
                      {
                          // special case for CtlColor to avoid too many temporary objects
                          ASSERT(message == WM_REFLECT_BASE+WM_CTLCOLOR);
                          AFX_CTLCOLOR* pCtl = reinterpret_cast<AFX_CTLCOLOR*>(lParam);
                          CDC dcTemp;
                          dcTemp.m_hDC = pCtl->hDC;
                          UINT nCtlType = pCtl->nCtlType;
                          HBRUSH hbr = (this->*mmf.pfn_B_D_u)(&dcTemp, nCtlType);
                          // fast detach of temporary objects
                          dcTemp.m_hDC = NULL;
                          lResult = reinterpret_cast<LRESULT>(hbr);
                      }
                      break;
               
                  case AfxSig_i_u_W_u:
                      lResult = (this->*mmf.pfn_i_u_W_u)(LOWORD(wParam),
                          CWnd::FromHandle(reinterpret_cast<HWND>(lParam)), HIWORD(wParam));
                      break;
               
                  case AfxSig_i_uu_v:
                      lResult = (this->*mmf.pfn_i_u_u)(LOWORD(wParam), HIWORD(wParam));
                      break;
               
                  case AfxSig_i_W_uu:
                      lResult = (this->*mmf.pfn_i_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
                          LOWORD(lParam), HIWORD(lParam));
                      break;
               
                  case AfxSig_i_v_s:
                      lResult = (this->*mmf.pfn_i_s)(reinterpret_cast<LPTSTR>(lParam));
                      break;
               
                  case AfxSig_i_v_S:
                      lResult = (this->*mmf.pfn_i_S)(reinterpret_cast<LPCTSTR>(lParam));
                      break;
               
                  case AfxSig_v_F_b:
                      (this->*mmf.pfn_v_F_b)(CFont::FromHandle(reinterpret_cast<HFONT>(wParam)), (BOOL)LOWORD(lParam));
                      break;
               
                  case AfxSig_h_v_v:
                      {
                          HANDLE handle = (this->*mmf.pfn_h_v)();
                          lResult = reinterpret_cast<LRESULT>(handle);
                      }
                      break;
               
                  case AfxSig_h_b_h:
                      {
                          HANDLE handle = (this->*mmf.pfn_h_b_h)(static_cast<BOOL>(wParam), reinterpret_cast<HANDLE>(lParam));
                          lResult = reinterpret_cast<LRESULT>(handle);
                      }
                      break;
               
                  case AfxSig_h_h_h:
                      {
                          HANDLE handle = (this->*mmf.pfn_h_h_h)(reinterpret_cast<HANDLE>(wParam), reinterpret_cast<HANDLE>(lParam));
                          lResult = reinterpret_cast<LRESULT>(handle);
                      }
                      break;
               
                  case AfxSig_l_w_l:
                      lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam);
                      break;
               
                  case AfxSig_l_uu_M:
                      lResult = (this->*mmf.pfn_l_u_u_M)(LOWORD(wParam), HIWORD(wParam),
                          CMenu::FromHandle(reinterpret_cast<HMENU>(lParam)));
                      break;
                      
                  case AfxSig_v_b_h:
                      (this->*mmf.pfn_v_b_h)(static_cast<BOOL>(wParam),
                          reinterpret_cast<HANDLE>(lParam));
                      break;
               
                  case AfxSig_v_h_v:
                      (this->*mmf.pfn_v_h)(reinterpret_cast<HANDLE>(wParam));
                      break;
               
                  case AfxSig_v_h_h:
                      (this->*mmf.pfn_v_h_h)(reinterpret_cast<HANDLE>(wParam),
                          reinterpret_cast<HANDLE>(lParam));
                      break;
               
                  case AfxSig_v_v_v:
                      (this->*mmf.pfn_v_v)();
                      break;
               
                  case AfxSig_v_u_v:
                      (this->*mmf.pfn_v_u)(static_cast<UINT>(wParam));
                      break;
               
                  case AfxSig_v_up_v:
                      (this->*mmf.pfn_v_up)(static_cast<UINT_PTR>(wParam));
                      break;
               
                  case AfxSig_v_u_u:
                      (this->*mmf.pfn_v_u_u)(static_cast<UINT>(wParam), static_cast<UINT>(lParam));
                      break;
               
                  case AfxSig_v_uu_v:
                      (this->*mmf.pfn_v_u_u)(LOWORD(wParam), HIWORD(wParam));
                      break;
               
                  case AfxSig_v_v_ii:
                      (this->*mmf.pfn_v_i_i)(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
                      break;
               
                  case AfxSig_v_u_uu:
                      (this->*mmf.pfn_v_u_u_u)(static_cast<UINT>(wParam), LOWORD(lParam), HIWORD(lParam));
                      break;
               
                  case AfxSig_v_u_ii:
                      (this->*mmf.pfn_v_u_i_i)(static_cast<UINT>(wParam), LOWORD(lParam), HIWORD(lParam));
                      break;
               
                  case AfxSig_v_w_l:
                      (this->*mmf.pfn_v_w_l)(wParam, lParam);
                      break;
               
                  case AfxSig_MDIACTIVATE:
                      (this->*mmf.pfn_v_b_W_W)(m_hWnd == reinterpret_cast<HWND>(lParam),
                          CWnd::FromHandle(reinterpret_cast<HWND>(lParam)),
                          CWnd::FromHandle(reinterpret_cast<HWND>(wParam)));
                      break;
               
                  case AfxSig_MDINext:
                      (this->*mmf.pfn_v_W_b)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), static_cast<BOOL>(lParam));
                      break;
               
                  case AfxSig_v_D_v:
                      (this->*mmf.pfn_v_D)(CDC::FromHandle(reinterpret_cast<HDC>(wParam)));
                      break;
               
                  case AfxSig_v_M_v:
                      (this->*mmf.pfn_v_M)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam)));
                      break;
               
                  case AfxSig_v_M_ub:
                      (this->*mmf.pfn_v_M_u_b)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam)),
                          GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
                      break;
               
                  case AfxSig_v_W_v:
                      (this->*mmf.pfn_v_W)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)));
                      break;
               
                  case AfxSig_v_v_W:
                      (this->*mmf.pfn_v_W)(CWnd::FromHandle(reinterpret_cast<HWND>(lParam)));
                      break;
               
                  case AfxSig_v_W_uu:
                      (this->*mmf.pfn_v_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), LOWORD(lParam),
                          HIWORD(lParam));
                      break;
               
                  case AfxSig_v_W_p:
                      {
                          CPoint point(lParam);
                          (this->*mmf.pfn_v_W_p)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), point);
                      }
                      break;
               
                  case AfxSig_v_W_h:
                      (this->*mmf.pfn_v_W_h)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
                              reinterpret_cast<HANDLE>(lParam));
                      break;
               
                  case AfxSig_ACTIVATE:
                      (this->*mmf.pfn_v_u_W_b)(LOWORD(wParam),
                          CWnd::FromHandle(reinterpret_cast<HWND>(lParam)), HIWORD(wParam));
                      break;
               
                  case AfxSig_SCROLL:
                  case AfxSig_SCROLL_REFLECT:
                      {
                          // special case for WM_VSCROLL and WM_HSCROLL
                          ASSERT(message == WM_VSCROLL || message == WM_HSCROLL ||
                              message == WM_VSCROLL+WM_REFLECT_BASE || message == WM_HSCROLL+WM_REFLECT_BASE);
                          int nScrollCode = (short)LOWORD(wParam);
                          int nPos = (short)HIWORD(wParam);
                          if (lpEntry->nSig == AfxSig_SCROLL)
                              (this->*mmf.pfn_v_u_u_W)(nScrollCode, nPos,
                                  CWnd::FromHandle(reinterpret_cast<HWND>(lParam)));
                          else
                              (this->*mmf.pfn_v_u_u)(nScrollCode, nPos);
                      }
                      break;
               
                  case AfxSig_v_v_s:
                      (this->*mmf.pfn_v_s)(reinterpret_cast<LPTSTR>(lParam));
                      break;
               
                  case AfxSig_v_u_cs:
                      (this->*mmf.pfn_v_u_cs)(static_cast<UINT>(wParam), reinterpret_cast<LPCTSTR>(lParam));
                      break;
               
                  case AfxSig_OWNERDRAW:
                      (this->*mmf.pfn_v_i_s)(static_cast<int>(wParam), reinterpret_cast<LPTSTR>(lParam));
                      lResult = TRUE;
                      break;
               
                  case AfxSig_i_i_s:
                      lResult = (this->*mmf.pfn_i_i_s)(static_cast<int>(wParam), reinterpret_cast<LPTSTR>(lParam));
                      break;
               
                  case AfxSig_u_v_p:
                      {
                          CPoint point(lParam);
                          lResult = (this->*mmf.pfn_u_p)(point);
                      }
                      break;
               
                  case AfxSig_u_v_v:
                      lResult = (this->*mmf.pfn_u_v)();
                      break;
               
                  case AfxSig_v_b_NCCALCSIZEPARAMS:
                      (this->*mmf.pfn_v_b_NCCALCSIZEPARAMS)(static_cast<BOOL>(wParam),
                          reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam));
                      break;
               
                  case AfxSig_v_v_WINDOWPOS:
                      (this->*mmf.pfn_v_v_WINDOWPOS)(reinterpret_cast<WINDOWPOS*>(lParam));
                      break;
               
                  case AfxSig_v_uu_M:
                      (this->*mmf.pfn_v_u_u_M)(LOWORD(wParam), HIWORD(wParam), reinterpret_cast<HMENU>(lParam));
                      break;
               
                  case AfxSig_v_u_p:
                      {
                          CPoint point(lParam);
                          (this->*mmf.pfn_v_u_p)(static_cast<UINT>(wParam), point);
                      }
                      break;
               
                  case AfxSig_SIZING:
                      (this->*mmf.pfn_v_u_pr)(static_cast<UINT>(wParam), reinterpret_cast<LPRECT>(lParam));
                      lResult = TRUE;
                      break;
               
                  case AfxSig_MOUSEWHEEL:
                      lResult = (this->*mmf.pfn_b_u_s_p)(LOWORD(wParam), (short)HIWORD(wParam),
                          CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
                      if (!lResult)
                          return FALSE;
                      break;
                  case AfxSig_MOUSEHWHEEL:
                      (this->*mmf.pfn_MOUSEHWHEEL)(LOWORD(wParam), (short)HIWORD(wParam),
                          CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
                      break;
                  case AfxSig_l:
                      lResult = (this->*mmf.pfn_l_v)();
                      if (lResult != 0)
                          return FALSE;
                      break;
                  case AfxSig_u_W_u:
                      lResult = (this->*mmf.pfn_u_W_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), static_cast<UINT>(lParam));
                      break;
                  case AfxSig_v_u_M:
                      (this->*mmf.pfn_v_u_M)(static_cast<UINT>(wParam), CMenu::FromHandle(reinterpret_cast<HMENU>(lParam)));
                      break;
                  case AfxSig_u_u_M:
                      lResult = (this->*mmf.pfn_u_u_M)(static_cast<UINT>(wParam), CMenu::FromHandle(reinterpret_cast<HMENU>(lParam)));
                      break;
                  case AfxSig_u_v_MENUGETOBJECTINFO:
                      lResult = (this->*mmf.pfn_u_v_MENUGETOBJECTINFO)(reinterpret_cast<MENUGETOBJECTINFO*>(lParam));
                      break;
                  case AfxSig_v_M_u:
                      (this->*mmf.pfn_v_M_u)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam)), static_cast<UINT>(lParam));
                      break;
                  case AfxSig_v_u_LPMDINEXTMENU:
                      (this->*mmf.pfn_v_u_LPMDINEXTMENU)(static_cast<UINT>(wParam), reinterpret_cast<LPMDINEXTMENU>(lParam));
                      break;
                  case AfxSig_APPCOMMAND:
                      (this->*mmf.pfn_APPCOMMAND)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), static_cast<UINT>(GET_APPCOMMAND_LPARAM(lParam)), static_cast<UINT>(GET_DEVICE_LPARAM(lParam)), static_cast<UINT>(GET_KEYSTATE_LPARAM(lParam)));
                      lResult = TRUE;
                      break;
                  case AfxSig_RAWINPUT:
                      (this->*mmf.pfn_RAWINPUT)(static_cast<UINT>(GET_RAWINPUT_CODE_WPARAM(wParam)), reinterpret_cast<HRAWINPUT>(lParam));
                      break;
                  case AfxSig_u_u_u:
                      lResult = (this->*mmf.pfn_u_u_u)(static_cast<UINT>(wParam), static_cast<UINT>(lParam));
                      break;
                  case AfxSig_u_u_l:
                      lResult = (this->*mmf.pfn_u_u_l)(static_cast<UINT>(wParam), lParam);
                      break;
                  case AfxSig_MOUSE_XBUTTON:
                      (this->*mmf.pfn_MOUSE_XBUTTON)(static_cast<UINT>(GET_KEYSTATE_WPARAM(wParam)), static_cast<UINT>(GET_XBUTTON_WPARAM(wParam)), CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
                      lResult = TRUE;
                      break;
                  case AfxSig_MOUSE_NCXBUTTON:
                      (this->*mmf.pfn_MOUSE_NCXBUTTON)(static_cast<short>(GET_NCHITTEST_WPARAM(wParam)), static_cast<UINT>(GET_XBUTTON_WPARAM(wParam)), CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
                      lResult = TRUE;
                      break;
                  case AfxSig_INPUTLANGCHANGE:
                      (this->*mmf.pfn_INPUTLANGCHANGE)(static_cast<UINT>(wParam), static_cast<UINT>(lParam));
                      lResult = TRUE;
                      break;
                  case AfxSig_INPUTDEVICECHANGE:
                      (this->*mmf.pfn_INPUTDEVICECHANGE)(LOWORD(wParam), reinterpret_cast<HANDLE>(lParam));
                      break;
                  case AfxSig_v_u_hkl:
                      (this->*mmf.pfn_v_u_h)(static_cast<UINT>(wParam), reinterpret_cast<HKL>(lParam));
                      break;
                  case AfxSig_b_v_ii:
                      lResult = (this->*mmf.pfn_b_v_ii)(GET_Y_LPARAM(lParam), GET_X_LPARAM(lParam));
                      break;
                  }
                  goto LReturnTrue;
               
              LDispatchRegistered:    // for registered windows messages
                  ASSERT(message >= 0xC000);
                  ASSERT(sizeof(mmf) == sizeof(mmf.pfn));
                  mmf.pfn = lpEntry->pfn;
                  lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam);
               
              LReturnTrue:
                  if (pResult != NULL)
                      *pResult = lResult;
                  return TRUE;
              }

            Как тебе? Любишь такой код сопровождать? Или сам такой код и пишешь?

            Ну и вишенка на тортик:
            C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\com\administration\spy\comspyctl\Adminwrap.Cpp
            ExpandedWrap disabled
              #include "stdafx.h"
              #include "Adminwrap.h"
              #include <comadmin.h>
              #include <assert.h>
               
              #define if_failed_exit(HR)      do { if FAILED(HR) goto exit; } while (false)
              #define exit_with_result(HR)    do { hr = HR; goto exit; } while (false)

            :lol: :lol: :lol: :lol:
            Сообщение отредактировано: KILLER -
              Цитата KILLER @
              По поводу кода - на держи

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


              Цитата KILLER @
              Он не в тему тем, что ты пришел, тему не читал, зато начал что то писать. Я тебе говорю - твой пример не в тему, и не привожу почему - чтоб ты взял и сам перечитал.

              Это называется съехал. Понятно.

              Добавлено
              Цитата KILLER @
              А это! Это просто шедевр!!! cppasm, помнишь обвинял меня в том, что я бла бла бла

              И где тут анонсированное:
              Цитата KILLER @
              goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки, и потом таким же макросом расставлены метки?

              Кривой тут только последний пример, остальное нормально читается.
                Цитата
                Так приведи мне хоть один пример, когда goto делает код более понятным?

                Ты сам привел такой пример:

                Цитата
                inline HRESULT CSecurityDescriptor::SetPrivilege

                Вариант с goto читаем. Использование do{...}while(false); сделало бы этот код хуже читаемым.
                  К слову - действительно причём здесь SDK?
                  Это не SDK, это сэмплы из SDK. Я их например вообще не ставлю никогда, и что?
                  И почему SDK v7.0 а не v7.1, чтоб другим проверить сложнее было?
                    Цитата cppasm @
                    И нафига ты проверку дублируешь?

                    Чтоб выйти из внешнего цикла, я ведь даже подход к решению задачи не менял. Можно переписать и мой код по другому. Я тебе его написал на коленке, чтобы показать идею, как можно переписать твой код без goto, примерно так же как и ты мне его написал на коленке. Возможно там вообще можно было обойтись еще проще. Я не знаю, мне пока не интересно придумывать 100500 разных вариантов решения твоей задачи.

                    Цитата cppasm @
                    Так понятней читать что-ли, для тех кто с первого раза не понимает? :)

                    У тебя выход по goto идет из вложенного цикла за внешний цикл. Поэтому я сделал там вторую проверку, просто твой вложенный цикл обернул в отдельную функцию.

                    Цитата cppasm @
                    От того что ты кусок кода в функцию вынес как-то лучше не стало.

                    Стало. Код стал намного понятнее, так как там уже не двойной цикл не пойми зачем идет, а появилась какая то логика происходящего + мы избавились от goto и вырвиглазного кода.

                    Цитата cppasm @
                    Это называется съехал. Понятно.

                    Хорошо, на держи бла бла бла:
                    Цитата KILLER @
                    Возможно в каких то там исключительных случаях - когда тебе нужно выйти из 4-ого по вложенности цикла - оно и упрощает понимание кода, но в тех примерах где они его используют, там и без goto обойтись не составляет проблем, без нарушения структуры исполнения программы.

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

                    Цитата cppasm @
                    И где тут анонсированное:

                    Повылазило? Ну хорошо еще раз:
                    ExpandedWrap disabled
                          #include "stdafx.h"
                          #include "Adminwrap.h"
                          #include <comadmin.h>
                          #include <assert.h>
                          #define if_failed_exit(HR)      do { if FAILED(HR) goto exit; } while (false) //<<<<<<<<<<<<<<<< goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки
                          #define exit_with_result(HR)    do { hr = HR; goto exit; } while (false)     //<<<<<<<<<<<<<<<< goto вхерачен в макрос, который представляет из себя часть какой то то ли функции, то ли проверки


                    Цитата cppasm @
                    Кривой тут только последний пример, остальное нормально читается.

                    Нормально читается? :wall: А что имея под рукой классы, кучу идиом и паттернов - по другому нельзя нормально переписать? А с использованием лямбд из нового стандарта, так даже можно и классы не применять, функции очистки и RAII можно клепать прямо на лету, где тебе нужно, без написания всяких оберток.

                    Например из последнего, то что было с goto и я переписывал без goto:
                    Мой код:
                    ExpandedWrap disabled
                          DWORD COMUtility::SetAccountRights(const std::wstring& sUser, const std::wstring& sPrivilege)
                          {
                              auto LSAHandleDeleter = [](LSA_HANDLE* hPolicy)
                              {
                                  if (hPolicy && *hPolicy)
                                      LsaClose(*hPolicy);
                              };
                       
                              std::unique_ptr<LSA_HANDLE, decltype(LSAHandleDeleter)> smartLSAHandle(nullptr, LSAHandleDeleter);
                              LSA_HANDLE                                              rawLSAHandle = nullptr;
                              LSA_OBJECT_ATTRIBUTES                                   objectAttributes = { 0 };
                              std::unique_ptr<SID>                                    psidPrincipal;
                              LSA_UNICODE_STRING                                      lsaPrivilegeString = { 0 };
                              WCHAR                                                   wszPrivilege[256] = { 0 };
                              DWORD                                                   dwReturnValue = ERROR_SUCCESS;
                       
                              StringCchCopy(wszPrivilege, (sPrivilege.size() * sizeof(wchar_t)) + 1, sPrivilege.c_str());
                       
                              dwReturnValue = LsaOpenPolicy(NULL, &objectAttributes, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &rawLSAHandle);
                              dwReturnValue = LsaNtStatusToWinError(dwReturnValue);
                       
                              smartLSAHandle.reset(std::move(&rawLSAHandle));
                       
                              if (dwReturnValue != ERROR_SUCCESS)
                                  return dwReturnValue;
                       
                              psidPrincipal = GetPrincipalSID(sUser, dwReturnValue);
                              if (dwReturnValue != ERROR_SUCCESS)
                                  return dwReturnValue;
                       
                              lsaPrivilegeString.Length = (USHORT)(wcslen(wszPrivilege) * sizeof(WCHAR));
                              lsaPrivilegeString.MaximumLength = (USHORT)(lsaPrivilegeString.Length + sizeof(WCHAR));
                              lsaPrivilegeString.Buffer = wszPrivilege;
                       
                              dwReturnValue = LsaAddAccountRights(*smartLSAHandle, psidPrincipal.get(), &lsaPrivilegeString, 1);
                              dwReturnValue = LsaNtStatusToWinError(dwReturnValue);
                       
                              return dwReturnValue;
                          }


                    Оригинал от майкрософта:
                    ExpandedWrap disabled
                       * NAME: SetAccountRights                                                    *
                       * --------------------------------------------------------------------------*
                       * DESCRIPTION: Sets the account right for a given user.                     *
                      \*---------------------------------------------------------------------------*/
                      DWORD SetAccountRights (
                          LPTSTR tszUser,
                          LPTSTR tszPrivilege
                          )
                      {
                          LSA_HANDLE            hPolicy            = NULL;
                          LSA_OBJECT_ATTRIBUTES objectAttributes   = {0};
                          PSID                  psidPrincipal      = NULL;
                          LSA_UNICODE_STRING    lsaPrivilegeString = {0};
                          WCHAR                 wszPrivilege [256] = {0};
                          DWORD                dwReturnValue       = ERROR_SUCCESS;
                       
                      #ifdef _UNICODE
                          StringCchCopy (wszPrivilege, RTL_NUMBER_OF(wszPrivilege),tszPrivilege);
                      #else
                          STR2UNI (wszPrivilege, tszPrivilege);
                      #endif
                       
                          dwReturnValue = LsaOpenPolicy (NULL,
                                                         &objectAttributes,
                                                         POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
                                                         &hPolicy);
                                                        
                          dwReturnValue = LsaNtStatusToWinError(dwReturnValue);
                       
                          if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP;
                       
                          dwReturnValue = GetPrincipalSID (tszUser, &psidPrincipal);
                          if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP;
                       
                          lsaPrivilegeString.Length = (USHORT) (wcslen (wszPrivilege) * sizeof (WCHAR));
                          lsaPrivilegeString.MaximumLength = (USHORT) (lsaPrivilegeString.Length + sizeof (WCHAR));
                          lsaPrivilegeString.Buffer = wszPrivilege;
                       
                          dwReturnValue = LsaAddAccountRights (hPolicy,
                                                               psidPrincipal,
                                                               &lsaPrivilegeString,
                                                               1);
                       
                          dwReturnValue = LsaNtStatusToWinError(dwReturnValue);
                       
                          if (dwReturnValue != ERROR_SUCCESS) goto CLEANUP;
                          
                       
                      CLEANUP:
                       
                          if(psidPrincipal) free (psidPrincipal);
                          if(hPolicy) LsaClose (hPolicy);
                       
                          return dwReturnValue;
                      }

                    И я сейчас не упрекаю их за то, что они там лямбды не повпихивали, или что они там std::wstring не использовали. Я тебе просто показываю как можно переписать без goto. Пусть этот код у них Сишный, но ведь С++сный код , что я привел выше - написан в том же стиле.
                    Ты считаешь это нормальным? А для меня это не нормально. Для меня более понятно и привычно то, как переписал я. Хотя возможно, и я не отрицаю у меня вырвиглазный код и его можно переписать еще лучше и круче. У меня не было цели рефакторить все, я избавился от goto и от ручного выделения/освобождения памяти.

                    Цитата Fester @
                    Вариант с goto читаем. Использование do{...}while(false); сделало бы этот код хуже читаемым.

                    Зачем переписывать на do while? Я вот по другому переписал. Мне мой подход - более понятен, чем этот оцтой.

                    Добавлено
                    Цитата cppasm @
                    К слову - действительно причём здесь SDK?
                    Это не SDK, это сэмплы из SDK. Я их например вообще не ставлю никогда, и что?
                    И почему SDK v7.0 а не v7.1, чтоб другим проверить сложнее было?

                    Посмотри другие версии. Если человек так пишет в семплах - то он так же будет писать в проде. Ну не можешь ты в проде писать вот так, а в семплах вот так. Это уже какой то троллинг получается.
                    Сообщение отредактировано: KILLER -
                      Цитата
                      Я вот по другому переписал. Мне мой подход - более понятен, чем этот оцтой.

                      Во-первых, твой вариант - не эквивалентен варианту от MS. У них в клинапе есть еще
                      ExpandedWrap disabled
                        if(psidPrincipal) free (psidPrincipal);
                      а ты про это почему-то забыл ;)
                      Во-вторых, лямбды появились не так давно. Или ты полагаешь, что как только появилась новая цаца, так сразу МС должны переписать все библиотеки?
                        Цитата KILLER @
                        Повылазило? Ну хорошо еще раз

                        Ты попроще общаться не пробовал?
                        Вот покажи конкретно где там
                        Цитата KILLER @
                        и потом таким же макросом расставлены метки

                        В противном случае у кого повылазило станет очевидно.
                        Сообщение отредактировано: cppasm -
                          Цитата Fester @
                          Во-первых, твой вариант - не эквивалентен варианту от MS. У них в клинапе есть еще
                          CollapsedWrap disabledLine numbers off

                          if(psidPrincipal) free (psidPrincipal);

                          а ты про это почему-то забыл ;)

                          Нет не забыл. Просто ты видимо С++ не знаешь.

                          Цитата Fester @
                          Во-вторых, лямбды появились не так давно. Или ты полагаешь, что как только появилась новая цаца, так сразу МС должны переписать все библиотеки?

                          А ты не читатель?
                          До лямбд уже 100 лет как успешно применяется идиома RAII. Почему MFC/ATL изначально не спроектировать на основе этой идиомы? Зачем там пихать goto ?

                          Цитата cppasm @
                          Ты попроще общаться не пробовал?

                          Если ты не читатель - как еще обращаться? Меня бесит когда человек не читает, но мнение имеет.

                          Цитата cppasm @
                          В противном случае у кого повылазило станет очевидно.

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

                          Добавлено
                          Еще один треш от майкрософта:
                          ExpandedWrap disabled
                            #define __LONGSTRING(string) L##string
                            #define LONGSTRING(string) __LONGSTRING(string)
                             
                            //Goes to CLEANUP on Failure
                            #define CHECK_HR(hr)            \
                                if(FAILED(hr))              \
                                    goto CLEANUP
                             
                            //Goes to CLEANUP on Failure, and displays any ErrorInfo
                            #define XCHECK_HR(hr)                                               \
                            {                                                                   \
                                if( g_dwFlags & DISPLAY_METHODCALLS )                           \
                                    fwprintf(stderr, LONGSTRING(#hr) L"\n");                    \
                                if(FAILED(myHandleResult(hr, LONGSTRING(__FILE__), __LINE__)))  \
                                    goto CLEANUP;                                               \
                            }
                            #define CHECK_MEMORY(hr, pv)    \
                            {                               \
                                if(!pv)                     \
                                {                           \
                                    hr = E_OUTOFMEMORY;     \
                                    CHECK_HR(hr);           \
                                }                           \
                            }
                            Цитата KILLER @
                            По поводу кода - на держи:
                            ...
                            Ну вот и говнокоду прибыло. KILLER, ты в натуре считаешь, что код от такой переделки выиграл? В чём? Наглядности? Скорости? Объёму? Ото ж, ради галочки. Попробуй теперь вот тут:
                            ExpandedWrap disabled
                              int copyFile(const char* src, const char* dst)
                              {
                                void *buf = NULL;
                                FILE *inF = NULL;
                                FILE *ouF = NULL;
                                size_t readed, written;
                                int   res = 0;
                               
                                buf = malloc(BUF_SIZE);
                                inF = fopen(src, "rb");
                                ouF = fopen(dst, "wb");
                               
                                if (buf == NULL) goto cleanup;
                                if (inF == NULL) goto cleanup;
                                if (ouF == NULL) goto cleanup;
                               
                                readed = fread(buf, 1, BUF_SIZE, inF);
                                while (!feof(inF) || readed != 0)
                                {
                                  written = fwrite(buf, 1, readed, ouF);
                                  if (written != readed) goto cleanup;
                                  readed = fread(buf, 1, BUF_SIZE, inF);
                                }
                                res = 1;
                               
                              cleanup:
                                if (ouF != NULL) fclose(ouF);
                                if (inF != NULL) fclose(inF);
                                if (buf != NULL) free(buf);
                               
                                return res;
                              }
                            С примерами в MSDN такая же хрень, их без __leave нормально не написать.
                            Цитата KILLER @
                            Хорошо, кинь мне ссылку на описание этого паттерна, впервые о таком слышу.
                            Керниган, Ричи. Язык C, раздел "3.9. Оператор GOTO и метки"
                            Цитата KILLER @
                            Может тоже буду применять у себя.
                            Не стоит. Хотя для слабеньких встроенных систем он и сегодня полезен, фактически за пределамиы POSIX, в котором отсутствует SEH или его аналог, он уже не применяется. Да-да-да, но смирись, что примеры в MSDN никто переписывать не будет.

                            Добавлено
                            Цитата KILLER @
                            Я так полагаю вы будете заводить 10 разный меток, и прыгать? Да? Судя по всему да.
                            А вот и нет. См. код выше. Ты ж не заводишь 10 finally... или заводишь? <_<
                              Цитата Qraizer @
                              Ну вот и говнокоду прибыло. KILLER, ты в натуре считаешь, что код от такой переделки выиграл?

                              В восприятии - да выиграл. Его стало проще воспринимать. Искать глазами метку - это треш, особенно если код не из 4 строчек, как привел cppasm.

                              Цитата Qraizer @
                              Керниган, Ричи. Язык C, раздел "3.9. Оператор GOTO и метки"

                              Цитата

                              В языке "C" предусмотрен и оператор GOTO, которым беско-
                              нечно злоупотребляют, и метки для ветвления. С формальной
                              точки зрения оператор GOTO никогда не является необходимым,
                              и на практике почти всегда можно обойтись без него.


                              Дальше читать не стал. Даже K&R считают что в Си им злоупотребляют, и практически всегда можно обойтись без него. ЧТД.

                              Цитата Qraizer @
                              Да-да-да, но смирись, что примеры в MSDN никто переписывать не будет.

                              Так я не прошу чтоб они их переписывали, они новые клепают на том же goto. Я тут уже привел достаточно кода из ATL/MFC что писалось исключительно на С++, для демонстрации их подхода.

                              Цитата Qraizer @

                              int copyFile(const char* src, const char* dst)
                              {
                              void *buf = NULL;
                              FILE *inF = NULL;
                              FILE *ouF = NULL;
                              size_t readed, written;

                              buf = malloc(BUF_SIZE);
                              inF = fopen(src, "rb");
                              ouF = fopen(dst, "wb");

                              if (buf == NULL) goto cleanup;
                              if (inF == NULL) goto cleanup;
                              if (ouF == NULL) goto cleanup;

                              readed = fread(buf, 1, BUF_SIZE, inF);
                              while (!feof(inF) || readed != 0)
                              {
                              written = fwrite(buf, 1, readed, ouF);
                              if (written != readed) goto cleanup;
                              readed = fread(buf, 1, BUF_SIZE, inF);
                              }
                              return 1;

                              cleanup:
                              if (ouF != NULL) fclose(ouF);
                              if (inF != NULL) fclose(inF);
                              if (buf != NULL) free(buf);

                              return 0;
                              }

                              Выше ведь приводил уже:
                              ExpandedWrap disabled
                                 auto LSAHandleDeleter = [](LSA_HANDLE* hPolicy)
                                        {
                                            if (hPolicy && *hPolicy)
                                                LsaClose(*hPolicy);
                                        };

                              Поменяй название LSA_HANDLE на FILE и все перепишется на ура. На крайний случай это все легко переписывается с помощью идиомы RAII. И не нужно следить забыл я закрыть файл или удалить буфер.
                              Сообщение отредактировано: KILLER -
                                Цитата OpenGL @
                                Структурный вариант в той теме был, но с goto он мог соревноваться только с краткостью записи, но никак не с понятностью (там сложная логика в условиях выхода из циклов, и неочевидный инкремент были).
                                Ещё он писался в несколько приёмов и отлаживался. С goto написалось с первого раза и заработало без отладки.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (12) 1 2 [3] 4 5 ...  11 12 все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,1012 ]   [ 18 queries used ]   [ Generated: 19.04.24, 02:21 GMT ]