QNX.ORG.RU

Общее => Ошибки в QNX 6 => Тема начата: DavASko от Сентября 16, 2013, 03:25:35 pm



Название: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: DavASko от Сентября 16, 2013, 03:25:35 pm
Проект системы реального времени и собственно программа мне достались недавно, программирую их не так давно. Под QNX она разработана на языке C в среде QNX Mometix IDE v.6.3.2  под систему Photon. При компиляции проекта, построенного с применением GUI-окон вылазит ошибка:
Код:
make -k CPULIST=x86 EXCLUDE_VARIANTLIST=be/ VARIANTLIST=g clean all --file=C:/QNX632/ide4-workspace/cnc/src/ECM_machine/QMakefile22174.tmp
make -j 1 -Cx86 -fMakefile clean
make[1]: Entering directory `C:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86'
make -j 1 -Co-g -fMakefile clean
make[2]: Entering directory `C:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g'
C:/QNX632/host/win32/x86/usr/bin/rm -f  machine_g  *.pinfo *.o *.err *.map mapfile *.sym *.i   
make[2]: Leaving directory `C:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g'
make[1]: Leaving directory `C:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86'
make -j 1 -Cx86 -fMakefile all
make[1]: Entering directory `C:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86'
make -j 1 -Co-g -fMakefile all
make[2]: Entering directory `C:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g'
C:/QNX632/host/win32/x86/usr/bin/qcc -Vgcc_ntox86 -c -Wc,-Wall -Wc,-Wno-parentheses   -Wc,-Wall -Wc,-Wno-parentheses               -I. -I. -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86 -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/src -IC:/QNX632/target/qnx6/usr/include -IC:/QNX632/target/qnx6/usr/include     -I. -I. -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86 -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/src -IC:/QNX632/target/qnx6/usr/include -IC:/QNX632/target/qnx6/usr/include    -g   -DVARIANT_g  C:/QNX632/ide4-workspace/cnc/src/ECM_machine/src/abmain.c
C:/QNX632/host/win32/x86/usr/bin/qcc -Vgcc_ntox86 -c -Wc,-Wall -Wc,-Wno-parentheses   -Wc,-Wall -Wc,-Wno-parentheses               -I. -I. -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86 -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/src -IC:/QNX632/target/qnx6/usr/include -IC:/QNX632/target/qnx6/usr/include     -I. -I. -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86 -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine -IC:/QNX632/ide4-workspace/cnc/src/ECM_machine/src -IC:/QNX632/target/qnx6/usr/include -IC:/QNX632/target/qnx6/usr/include    -g   -DVARIANT_g  C:/QNX632/ide4-workspace/cnc/src/ECM_machine/src/base.c
C:/QNX632/host/win32/x86/usr/bin/rm -f  C:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g/machine_g
C:/QNX632/host/win32/x86/usr/bin/qcc -Vgcc_ntox86     -oC:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g/machine_g    abmain.o    base.o  -L. -LC:/QNX632/target/qnx6/x86/lib -LC:/QNX632/target/qnx6/x86/usr/lib   -lAp    -lph    -lm    -lAp    -lph    -lm   -g   
C:/QNX632/host/win32/x86/usr/bin/usemsg -s __USAGENTO -s __USAGE -iVERSION -iTAGID  C:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g/machine_g C:/QNX632/ide4-workspace/cnc/src/ECM_machine/src/Usemsg
phabbind machine_g C:/QNX632/ide4-workspace/cnc/src/ECM_machine/wgt/Icon.wgti C:/QNX632/ide4-workspace/cnc/src/ECM_machine/wgt/wnd_Base.wgtw C:/QNX632/ide4-workspace/cnc/src/ECM_machine/wgt/wnd_OptionsAUTO.wgtw
rm: Skipping c:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g/machine_g.res -- no write permission
bindres: command 'rm c:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g/machine_g.res' failed
make[2]: *** [C:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g/machine_g] Error 1
make[2]: Leaving directory `C:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g'
make[2]: Target `all' not remade because of errors.
make[1]: [all] Error 2 (ignored)
make[1]: Leaving directory `C:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86'
При проверке директорий все находится на своих местах. При том, проект был компилирован и в среде разработки под Windows и в самой среде QNX разные машины, но ошибка совершенно та же.
Подскажите мне пожалуйста как можно решить эту проблему. Уже неделю не могу проект собрать.


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: BrutNemo от Сентября 17, 2013, 08:47:32 am
не уверен..., но с
Цитировать
c:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g/machine_g.res
снимите флажок 'Только чтение'


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: DavASko от Сентября 17, 2013, 10:18:31 am
Это пробовал до этого, даже по всякому комбинировал, но, к сожалению, ничего не помогло :(


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: BrutNemo от Сентября 17, 2013, 10:49:52 am
снимите флажок 'Только чтение' + запустите Momentics от имени администратора


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: DavASko от Сентября 19, 2013, 08:14:46 am
Флажки не помогли.
Пмогла конфигурация make файла, а вернее конкретное описание пути для билда проекта......ю начиная из корневого каталога и до самой папки. Проект скомпилил, всем спасибо, кто попытался помочь.


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: da-nie от Мая 22, 2018, 09:33:03 pm
Чего-то я сегодня не понял, что за фигня.

Вот есть у меня класс квадратной матрицы (здесь уже исправленный вариант):
Код:
#ifndef CMATRIX_H
#define CMATRIX_H

#include <math.h>
#include <string.h>
#include "cvector.h"

//класс матрицы произвольной размерности
template<unsigned long size>
class CMatrix
{
 private:
  unsigned long Size;//размерность матрицы
  double *Item_Ptr;//указатель на массив компонентов матрицы
 public:
  CMatrix(void);//конструктор
  ~CMatrix(void);//деструктор
  CMatrix(const CMatrix<size> &cMatrix);//конструктор копирования
  double GetElement(unsigned long y,unsigned long x) const;//получить элемент матрицы
  void SetElement(unsigned long y,unsigned long x,double value);//задать элемент матрицы
  CMatrix<size>& operator=(const CMatrix<size>& cMatrix);//оператор "="
  friend CMatrix<size> operator+<size>(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right);//оператор "+"
  friend CMatrix<size> operator-<size>(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right);//оператор "-"
  friend CMatrix<size> operator*<size>(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right);//оператор "*"
  friend CMatrix<size> operator*<size>(const CMatrix<size>& cMatrix_Left,const double& value_right);//оператор "*"
  friend CMatrix<size> operator*<size>(const double& value_left,const CMatrix<size>& cMatrix_Right);//оператор "*"
  friend CVector<size> operator*<size>(const CMatrix<size> &cMatrix_Left,const CVector<size> &cVector_Right);//оператор "*"
  friend CVector<size> operator*<size>(const CVector<size> &cVector_Left,const CMatrix<size> &cMatrix_Right);//оператор "*"
  void Unitary(void);//привести к единичному виду
  void Zero(void);//обнулить матрицу
};

//====================================================================================================
//конструктор
//====================================================================================================
template<unsigned long size>
CMatrix<size>::CMatrix(void)
{
 Size=size;
 Item_Ptr=new double[Size*Size+1];
}
//====================================================================================================
//деструктор
//====================================================================================================
template<unsigned long size>
CMatrix<size>::~CMatrix(void)
{
 Size=0;
 delete[](Item_Ptr);
}
//====================================================================================================
//конструктор копирования
//====================================================================================================
template<unsigned long size>
CMatrix<size>::CMatrix(const CMatrix<size> &cMatrix)
{
 if (&cMatrix==this) return;
 Size=cMatrix.Size;
 Item_Ptr=new double[Size*Size+1];
 memcpy(Item_Ptr,cMatrix.Item_Ptr,Size*Size*sizeof(double));
}
//----------------------------------------------------------------------------------------------------
//получить элемент матрицы
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
double CMatrix<size>::GetElement(unsigned long y,unsigned long x) const
{
 if (x>=Size) return(0);
 if (y>=Size) return(0);
 return(Item_Ptr[size*y+x]);
}
//----------------------------------------------------------------------------------------------------
//задать элемент матрицы
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
void CMatrix<size>::SetElement(unsigned long y,unsigned long x,double value)
{
 if (x>=Size) return;
 if (y>=Size) return;
 Item_Ptr[size*y+x]=value;
}
//----------------------------------------------------------------------------------------------------
//оператор "="
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size>& CMatrix<size>::operator=(const CMatrix<size> &cMatrix)
{
 if (this!=&cMatrix)
 {
  if (Size*Size!=cMatrix.Size*cMatrix.Size)
  {
   Size=cMatrix.Size;
   if (Item_Ptr!=NULL) delete[](Item_Ptr);
   Item_Ptr=new double[Size*Size+1];
  }
  memcpy(Item_Ptr,cMatrix.Item_Ptr,Size*Size*sizeof(double));
 }
 return(*this);
}

//----------------------------------------------------------------------------------------------------
//оператор "+"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size> operator+(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right)
{
 CMatrix<size> cMatrix;
 for(unsigned long y=0;y<size;y++)
 {
  for(unsigned long x=0;x<size;x++)
  {
   cMatrix.Item_Ptr[size*y+x]=cMatrix_Left.Item_Ptr[size*y+x]+cMatrix_Right.Item_Ptr[size*y+x];
  }
 }
 return(cMatrix);
}
//----------------------------------------------------------------------------------------------------
//оператор "-"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size> operator-(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right)
{
 CMatrix<size> cMatrix;
 for(unsigned long y=0;y<size;y++)
 {
  for(unsigned long x=0;x<size;x++)
  {
   cMatrix.Item_Ptr[size*y+x]=cMatrix_Left.Item_Ptr[size*y+x]-cMatrix_Right.Item_Ptr[size*y+x];
  }
 }
 return(cMatrix);
}

//----------------------------------------------------------------------------------------------------
//оператор "*"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size> operator*(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right)
{
 CMatrix<size> cMatrix;
 double *m=cMatrix.Item_Ptr;
 for(unsigned long y=0;y<size;y++)
 {
  double *m1_begin=&cMatrix_Left.Item_Ptr[y*size];
  for(unsigned long x=0;x<size;x++,m++)
  {
   double s=0;
   double *m2=&cMatrix_Right.Item_Ptr[x];
   double *m1=m1_begin;
   for(unsigned long n=0;n<size;n++,m1++,m2+=size) s+=(*m1)*(*m2);
   *m=s;
  }
 }
 return(cMatrix);
}
//----------------------------------------------------------------------------------------------------
//оператор "*"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size> operator*(const CMatrix<size>& cMatrix_Left,const double& value_right)
{
 CMatrix<size> cMatrix;
 for(unsigned long y=0;y<size;y++)
 {
  for(unsigned long x=0;x<size;x++)
  {
   cMatrix.Item_Ptr[size*y+x]=cMatrix_Left.Item_Ptr[size*y+x]*value_right;
  }
 }
 return(cMatrix);
}
//----------------------------------------------------------------------------------------------------
//оператор "*"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size> operator*(const double& value_left,const CMatrix<size>& cMatrix_Right)
{
 CMatrix<size> cMatrix;
 for(unsigned long y=0;y<size;y++)
 {
  for(unsigned long x=0;x<size;x++)
  {
   cMatrix.Item_Ptr[size*y+x]=cMatrix_Right.Item_Ptr[size*y+x]*value_left;
  }
 }
 return(cMatrix);
}

//----------------------------------------------------------------------------------------------------
//оператор "*"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CVector<size> operator*(const CMatrix<size> &cMatrix_Left,const CVector<size> &cVector_Right)
{
 CVector<size> cVector;
 //умножается строка на столбец
 for(unsigned long y=0;y<size;y++)
 {
  double value=0;
  for(unsigned long x=0;x<size;x++)
  {
   double m_value=cMatrix_Left.Item_Ptr[size*y+x];
   double v_value=cVector_Right.GetElement(x);  
   value+=m_value*v_value;
  }
  cVector.SetElement(y,value);
 }
 return(cVector);
}
//----------------------------------------------------------------------------------------------------
//оператор "*"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CVector<size> operator*(const CVector<size> &cVector_Left,const CMatrix<size> &cMatrix_Right)
{
 CVector<size> cVector;
 //умножается строка на столбец
 for(unsigned long x=0;x<size;x++)
 {
  double value=0;
  for(unsigned long y=0;y<size;y++)
  {
   double m_value=cMatrix_Right.Item_Ptr[size*y+x];
   double v_value=cVector_Left.GetElement(y);
   value+=m_value*v_value;
  }
  cVector.SetElement(x,value);
 }
 return(cVector);
}

//----------------------------------------------------------------------------------------------------
//привести к единичному виду
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
void CMatrix<size>::Unitary(void)
{
 unsigned long ptr=0;
 for(unsigned long y=0;y<size;y++)
  for(unsigned long x=0;x<size;x++,ptr++)
  {
   if (x==y) Item_Ptr[ptr]=1;
        else Item_Ptr[ptr]=0;
  }
}

//----------------------------------------------------------------------------------------------------
//обнулить матрицу
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
void CMatrix<size>::Zero(void)
{
 unsigned long ptr=0;
 for(unsigned long y=0;y<size;y++)
  for(unsigned long x=0;x<size;x++,ptr++)
  {
   Item_Ptr[ptr]=0;
  }
}
#endif

Взял я его со старого проекта под Windows для компилятора VC6. А он в QNX 6.3 компилироваться отказался.
Вот это не нравится компилятору:
Код:
friend CMatrix<size> operator+(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right);//оператор "+"
Просит записать так: operator+<size>. Записал. Но в таком вот виде оно уже в VC6 не компилируется (попробую завтра в VC2010).
Что-то я не помню, чтобы при перегрузке оператора с шаблоном нужно было указывать <size>. Почему так в QNX? У Страуструпа я что-то такого не припомню.

Ну и ещё интересный вопрос - у меня оператор сделан friend. Хотелось бы, чтобы он был friend одновременно ещё и для другого шаблонного класса CVector (без этого приходится писать cVector_Left.GetElement(y), вместо прямого обращения к данным). Проблема в том, что CVector про CMatrix ничего не знает. А вот CMatrix про CVector знает. Я не могу подключить один в другой через include и в CVector прописать friend и такой же оператор - получится кольцо.


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: A_O от Мая 23, 2018, 09:52:26 am
Ну и ещё интересный вопрос - у меня оператор сделан friend. Хотелось бы, чтобы он был friend одновременно ещё и для другого шаблонного класса CVector (без этого приходится писать cVector_Left.GetElement(y), вместо прямого обращения к данным). Проблема в том, что CVector про CMatrix ничего не знает. А вот CMatrix про CVector знает. Я не могу подключить один в другой через include и в CVector прописать friend и такой же оператор - получится кольцо.
А #pragma once не может спасти гиганта мысли?


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: da-nie от Мая 23, 2018, 09:57:49 am
Так #pragma once не избавит от включения #include друг-друга в классах.  ::)


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: A_O от Мая 23, 2018, 03:56:28 pm
Так #pragma once не избавит от включения #include друг-друга в классах.  ::)
И на здоровье. Бесконечной петли не будет.


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: lastcross от Мая 23, 2018, 06:44:51 pm
Чего-то я сегодня не понял, что за фигня.

Вот есть у меня класс квадратной матрицы (здесь уже исправленный вариант):
Взял я его со старого проекта под Windows для компилятора VC6. А он в QNX 6.3 компилироваться отказался.
Не мешало показать точное сообщение компилятора. А учитывая что шаблоны компилируются в местах инстанцирования - то и код (максимально упращенный) на котором компилятор выводит ошибку.

Цитировать
Просит записать так: operator+<size>. Записал. Но в таком вот виде оно уже в VC6 не компилируется (попробую завтра в VC2010).
Что-то я не помню, чтобы при перегрузке оператора с шаблоном нужно было указывать <size>. Почему так в QNX? У Страуструпа я что-то такого не припомню.
Студия, особенно старая очень специфично работает с шаблонами и многие места, которые не по стандарту часто "проглатывает" (или наоборот). В целом - параметр шаблона при описании требуется указать, так как может быть множество имплементаций класса. Конкретные объяснения можно найти имея на руках конкретный пример (инстанцирования и ошибки компилятора).
Цитировать
Ну и ещё интересный вопрос - у меня оператор сделан friend. Хотелось бы, чтобы он был friend одновременно ещё и для другого шаблонного класса CVector

Зачем вам столько френдов? Делайте так:
  • Создавайте мембер-операторы
  • Все в одном хедере, если типы достижимы(видны) непосредственно для свободных функций - создавайте свободные функции на основе вызовов мемебер-операций
  • Если типы независимы между собой и лежат в разных хедерах - отдельный хедер для свободных функций операций пересечений. Либо же внутри хедера который находится в большей зависимости от других
  • Используйте форвард декларацию - это избавит вас от лишних потенциально циклических инклудов (хотя механизм имеет ряд ограничений)
  • Нет никакого смысла в одном хедере объявлять шаблонный класс с его членами и после описывать реализацию - делайте это сразу в объявлении класса. Это упрощает чтение шаблонов


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: lastcross от Мая 23, 2018, 07:03:56 pm
В добавок - зачем вам хранить размерность матрицы, если она уже передана в шаблоне. Вы таким способом только лишние байты на каждый объект матрицы используете. Ее можно сразу реализовать через метод:

Код:
template<unsigned long size>
CMatrix<size>::getSize(const CMatrix<size> &cMatrix)
{
  return size;
}

Учитывая что у вас не С++11 - то constexpr для этого метода не предлагаю =)


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: da-nie от Мая 23, 2018, 08:08:03 pm
Цитировать
Не мешало показать точное сообщение компилятора. А учитывая что шаблоны компилируются в местах инстанцирования - то и код (максимально упращенный) на котором компилятор выводит ошибку.

Фишка в том, что класс даже ещё не создавался - компилятор ругался просто на объявление класса. Если мне не изменяет память, там было написано что-то типа "Если у вас оператор не является членом класса, сделайте operator <...>". Завтра точнее смогу сказать.

Цитировать
В целом - параметр шаблона при описании требуется указать,

В операторе? Вот прям так: operator+<size>?

Цитировать
Зачем вам столько френдов

Чтобы оператор умножения матрицы на вектор имел доступ и к матрице и к вектору.

Цитировать
Если типы независимы между собой и лежат в разных хедерах - отдельный хедер для свободных функций операций пересечений.

Так криво же.

Цитировать
ет никакого смысла в одном хедере объявлять шаблонный класс с его членами и после описывать реализацию - делайте это сразу в объявлении класса. Это упрощает чтение шаблонов

Ну вообще, красиво когда объявление от реализации отделено. Ну и эти операторы не являются членами класса.

Цитировать
В добавок - зачем вам хранить размерность матрицы, если она уже передана в шаблоне. Вы таким способом только лишние байты на каждый объект матрицы используете. Ее можно сразу реализовать через метод:

Да как-то по инерции сохранил и параметр. :) Да, можно же выкинуть.

Цитировать
constexpr

Ну почему же, есть вроде как обновление на VC2010 с поддержкой C++11. А может, она и из коробки constexpr умеет. Я ещё не проверял. VC6, разумеется, точно его не знает, но я всё же перешёл на VC2010 для большинства проектов (остальные должны и под Windows 98 работать - им VC6). А... Конкретно этот же проект для QNX 6.3. Там, наверное, точно Си++ 11 не работает. :)


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: da-nie от Мая 23, 2018, 08:43:27 pm
Кстати, проверил. Visual Studio 2010 тоже отвергает синтаксис operator+<size>. Она хочет просто operator+. Но при этом проект компилируется, но не собирается. Линкер не может найти этот самый operator+.  ::) Пересоздал проект. Теперь не может и ряд методов класса найти. Перекомпилировал точно компилирующееся приложение - ошибка:
Код:
1>Link:
1>  Generating code
1>  Finished generating code
1>LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt
Чушь какая-то.  ::) Правда, у меня дома Windows 7 64 SP1, а студию я поставил для x86. На работе XP и студия тоже для x86. Может, в этом весь прикол. Как-то она криво работает.
Пишут, что такое случается, когда:

Код:
1)Вы запускаете VS 2010 после установки VS 2012.
2) Был установлен новый .Net Framework 4.5
3) Файлы .Net Framework 4 не в порядке (повреждены или удалены)
4) Файлы VS 2010 не в порядке.

Прикольно.  :-\

Возвращаясь к шаблонам. Всё-таки, как в QNX правильно и студия 2010 это приняла. Правда, иным образом. Вот тут написано (https://ru.stackoverflow.com/questions/495141/%d0%9f%d0%b5%d1%80%d0%b5%d0%b3%d1%80%d1%83%d0%b7%d0%ba%d0%b0-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d0%be%d0%b2-%d0%b8-%d0%b2-%d1%88%d0%b0%d0%b1%d0%bb%d0%be%d0%bd%d0%bd%d0%be%d0%bc-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%b5-%d0%ba%d0%b0%d0%ba-%d0%b4%d1%80%d1%83%d0%b6%d0%b5%d1%81%d1%82%d0%b2%d0%b5%d0%bd%d0%bd%d1%8b%d1%85-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b9).
Цитировать
...
Если Вам кажется, что объявление в классе и определение вне его должны быть как-то связаны, то это не так. Это две совершенно разные функции(одна шаблонная, а другая нет), а т.к., согласно ADL(argument-dependent lookup), при вызове оператора, поиск надлежащей функции будет проведён в классе, то компилятор находит нашу friend-декларацию:
friend ostream& operator << (ostream &, const Matrix<int> &);
Но вот реализации этой декларации нет, отсюда и ошибка компоновщика.
...

Но теперь, в классе Matrix, мы добавим в друзья специализацию этого шаблона:

friend ostream& operator <<<T>(ostream & os, const Matrix & rhs);
friend istream& operator >><T>(istream &, Matrix &);

А так как мы объявляем другом специализацию, то мы должны вынести определение(или только объявление) общего шаблона до класса Matrix.

Однако, в этом случае операторы нужно вытащить выше определения класса (ну или там их предварительно описать). Иначе они не находятся компилятором.  8)

И получается вот такой вот код:

Код:
#ifndef CMATRIX_H
#define CMATRIX_H

#include <math.h>
#include <string.h>
#include "cvector.h"

template<unsigned long size>
class CMatrix;

template<unsigned long size>
CMatrix<size> operator+(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right);//оператор "+"
template<unsigned long size>
CMatrix<size> operator-(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right);//оператор "-"
template<unsigned long size>
CMatrix<size> operator*(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right);//оператор "*"
template<unsigned long size>
CMatrix<size> operator*(const CMatrix<size>& cMatrix_Left,const double& value_right);//оператор "*"
template<unsigned long size>
CMatrix<size> operator*(const double& value_left,const CMatrix<size>& cMatrix_Right);//оператор "*"
template<unsigned long size>
CVector<size> operator*(const CMatrix<size> &cMatrix_Left,const CVector<size> &cVector_Right);//оператор "*"
template<unsigned long size>
CVector<size> operator*(const CVector<size> &cVector_Left,const CMatrix<size> &cMatrix_Right);//оператор "*"

//класс матрицы произвольной размерности
template<unsigned long size>
class CMatrix
{
 private:
  double *Item_Ptr;//указатель на массив компонентов матрицы
 public:
  CMatrix(void);//конструктор
  ~CMatrix(void);//деструктор
  CMatrix(const CMatrix<size> &cMatrix);//конструктор копирования
  double GetElement(unsigned long y,unsigned long x) const;//получить элемент матрицы
  void SetElement(unsigned long y,unsigned long x,double value);//задать элемент матрицы
  CMatrix<size>& operator=(const CMatrix<size>& cMatrix);//оператор "="
  friend CMatrix<size> operator+<size>(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right);//оператор "+"
  friend CMatrix<size> operator-<size>(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right);//оператор "-"
  friend CMatrix<size> operator*<size>(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right);//оператор "*"
  friend CMatrix<size> operator*<size>(const CMatrix<size>& cMatrix_Left,const double& value_right);//оператор "*"
  friend CMatrix<size> operator*<size>(const double& value_left,const CMatrix<size>& cMatrix_Right);//оператор "*"
  friend CVector<size> operator*<size>(const CMatrix<size> &cMatrix_Left,const CVector<size> &cVector_Right);//оператор "*"
  friend CVector<size> operator*<size>(const CVector<size> &cVector_Left,const CMatrix<size> &cMatrix_Right);//оператор "*"
  void Unitary(void);//привести к единичному виду
  void Zero(void);//обнулить матрицу
};

//====================================================================================================
//конструктор
//====================================================================================================
template<unsigned long size>
CMatrix<size>::CMatrix(void)
{
 Item_Ptr=new double[size*size+1];
}
//====================================================================================================
//деструктор
//====================================================================================================
template<unsigned long size>
CMatrix<size>::~CMatrix(void)
{
 delete[](Item_Ptr);
}
//====================================================================================================
//конструктор копирования
//====================================================================================================
template<unsigned long size>
CMatrix<size>::CMatrix(const CMatrix<size> &cMatrix)
{
 if (&cMatrix==this) return;
 Item_Ptr=new double[size*size+1];
 memcpy(Item_Ptr,cMatrix.Item_Ptr,size*size*sizeof(double));
}
//----------------------------------------------------------------------------------------------------
//получить элемент матрицы
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
double CMatrix<size>::GetElement(unsigned long y,unsigned long x) const
{
 if (x>=size) return(0);
 if (y>=size) return(0);
 return(Item_Ptr[size*y+x]);
}
//----------------------------------------------------------------------------------------------------
//задать элемент матрицы
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
void CMatrix<size>::SetElement(unsigned long y,unsigned long x,double value)
{
 if (x>=size) return;
 if (y>=size) return;
 Item_Ptr[size*y+x]=value;
}
//----------------------------------------------------------------------------------------------------
//оператор "="
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size>& CMatrix<size>::operator=(const CMatrix<size> &cMatrix)
{
 if (this!=&cMatrix)
 {
  memcpy(Item_Ptr,cMatrix.Item_Ptr,size*size*sizeof(double));
 }
 return(*this);
}

//----------------------------------------------------------------------------------------------------
//оператор "+"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size> operator+(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right)
{
 CMatrix<size> cMatrix;
 for(unsigned long y=0;y<size;y++)
 {
  for(unsigned long x=0;x<size;x++)
  {
   cMatrix.Item_Ptr[size*y+x]=cMatrix_Left.Item_Ptr[size*y+x]+cMatrix_Right.Item_Ptr[size*y+x];
  }
 }
 return(cMatrix);
}
//----------------------------------------------------------------------------------------------------
//оператор "-"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size> operator-(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right)
{
 CMatrix<size> cMatrix;
 for(unsigned long y=0;y<size;y++)
 {
  for(unsigned long x=0;x<size;x++)
  {
   cMatrix.Item_Ptr[size*y+x]=cMatrix_Left.Item_Ptr[size*y+x]-cMatrix_Right.Item_Ptr[size*y+x];
  }
 }
 return(cMatrix);
}

//----------------------------------------------------------------------------------------------------
//оператор "*"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size> operator*(const CMatrix<size>& cMatrix_Left,const CMatrix<size>& cMatrix_Right)
{
 CMatrix<size> cMatrix;
 double *m=cMatrix.Item_Ptr;
 for(unsigned long y=0;y<size;y++)
 {
  double *m1_begin=&cMatrix_Left.Item_Ptr[y*size];
  for(unsigned long x=0;x<size;x++,m++)
  {
   double s=0;
   double *m2=&cMatrix_Right.Item_Ptr[x];
   double *m1=m1_begin;
   for(unsigned long n=0;n<size;n++,m1++,m2+=size) s+=(*m1)*(*m2);
   *m=s;
  }
 }
 return(cMatrix);
}
//----------------------------------------------------------------------------------------------------
//оператор "*"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size> operator*(const CMatrix<size>& cMatrix_Left,const double& value_right)
{
 CMatrix<size> cMatrix;
 for(unsigned long y=0;y<size;y++)
 {
  for(unsigned long x=0;x<size;x++)
  {
   cMatrix.Item_Ptr[size*y+x]=cMatrix_Left.Item_Ptr[size*y+x]*value_right;
  }
 }
 return(cMatrix);
}
//----------------------------------------------------------------------------------------------------
//оператор "*"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CMatrix<size> operator*(const double& value_left,const CMatrix<size>& cMatrix_Right)
{
 CMatrix<size> cMatrix;
 for(unsigned long y=0;y<size;y++)
 {
  for(unsigned long x=0;x<size;x++)
  {
   cMatrix.Item_Ptr[size*y+x]=cMatrix_Right.Item_Ptr[size*y+x]*value_left;
  }
 }
 return(cMatrix);
}

//----------------------------------------------------------------------------------------------------
//оператор "*"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CVector<size> operator*(const CMatrix<size> &cMatrix_Left,const CVector<size> &cVector_Right)
{
 CVector<size> cVector;
 //умножается строка на столбец
 for(unsigned long y=0;y<size;y++)
 {
  double value=0;
  for(unsigned long x=0;x<size;x++)
  {
   double m_value=cMatrix_Left.Item_Ptr[size*y+x];
   double v_value=cVector_Right.GetElement(x);  
   value+=m_value*v_value;
  }
  cVector.SetElement(y,value);
 }
 return(cVector);
}
//----------------------------------------------------------------------------------------------------
//оператор "*"
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
CVector<size> operator*(const CVector<size> &cVector_Left,const CMatrix<size> &cMatrix_Right)
{
 CVector<size> cVector;
 //умножается строка на столбец
 for(unsigned long x=0;x<size;x++)
 {
  double value=0;
  for(unsigned long y=0;y<size;y++)
  {
   double m_value=cMatrix_Right.Item_Ptr[size*y+x];
   double v_value=cVector_Left.GetElement(y);
   value+=m_value*v_value;
  }
  cVector.SetElement(x,value);
 }
 return(cVector);
}

//----------------------------------------------------------------------------------------------------
//привести к единичному виду
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
void CMatrix<size>::Unitary(void)
{
 unsigned long ptr=0;
 for(unsigned long y=0;y<size;y++)
  for(unsigned long x=0;x<size;x++,ptr++)
  {
   if (x==y) Item_Ptr[ptr]=1;
        else Item_Ptr[ptr]=0;
  }
}

//----------------------------------------------------------------------------------------------------
//обнулить матрицу
//----------------------------------------------------------------------------------------------------
template<unsigned long size>
void CMatrix<size>::Zero(void)
{
 unsigned long ptr=0;
 for(unsigned long y=0;y<size;y++)
  for(unsigned long x=0;x<size;x++,ptr++)
  {
   Item_Ptr[ptr]=0;
  }
}
#endif

Странно, правда, что в QNX не потребовалось делать предварительное описание.  ::)


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: lastcross от Мая 24, 2018, 09:01:14 pm
Цитировать
В операторе? Вот прям так: operator+<size>?

Тут можно почитать (http://en.cppreference.com/w/cpp/language/friend). Конкретнее в "Template friend operators"
Именно по этому я и намекал, что френды скорее всего вам не нужны. И если отойти от их использования, то можно прийти к тому что внутри описания шаблонного класса можно описывать реализацию методов (собственных операторов - а это избавит вас от лишнего указания <>). Нужны операторы внешние? Тогда реализовывайте их через - другую абстракцию (абстракцию доступа - если у вас полная инкапсуляция), или через менее связанные типы, или через forward declaration/


Цитировать
Так криво же.

Не криво - а модульно. Френды это одна из жестких связей (на ровне с наследованием). Наличие френдов заставляет предоставлять (с учетом шаблонов) все сразу - хотя пользователю нужна лишь часть (хочет вектор, а тянет с собой и матрицу и операции с ними, включая кватернионы ).

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

У вас и члены класса и френды все за пределами описания класса. Вот это криво (так как приходится и без того сложные шаблоны изучать бегая по тексту). Не члены класса (френды) - реализовывать вне класса - норм.



Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: da-nie от Мая 24, 2018, 09:41:09 pm
Цитировать
Именно по этому я и намекал, что френды скорее всего вам не нужны.

Так это стандартный подход. :-\

Цитировать
Не криво - а модульно.

С этим не поспорить - модульно. Надо подумать.

Цитировать
хочет вектор, а тянет с собой и матрицу и операции с ними, включая кватернионы

Есть и кватернионы в этом наборе. :) Собственно, всё это ради них и делалось - они широко используются в системе ориентации космического аппарата.

Цитировать
У вас и члены класса и френды все за пределами описания класса. Вот это криво (так как приходится и без того сложные шаблоны изучать бегая по тексту). Не члены класса (френды) - реализовывать вне класса - норм.

У нас с вами разные вкусы. :) Мне не нравится, когда класс напичкан реализациями функций - там теряется начало одной функции и конец другой. Смотришь на класс и не понимаешь, а какой же у него интерфейс? Нет, я предпочитаю реализацию отделять от описания. В этом случае сразу видно, что умеет класс.

Пользуясь случаем, также спрошу у вас один занятный вопрос: может вы знаете, зачем нужны замыкания функций? Я от современной функциональщины очень далёк (а от чтения руководства по Haskel остаётся недоумение, зачем и кому всё это нужно) и её просто не понимаю. Потому и не нахожу ни одной причины для использования замыкания и извращений с ним связанным в Си++.  :-\ Надуманные примеры я видел, но они именно что "а вот теперь мы можем и вот так". Ну, можем. А... зачем? :)


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: lastcross от Мая 25, 2018, 11:08:15 am
Цитировать
Так это стандартный подход. :-\

Это не "стандартный" подход (в понимании стандарта - он не является ни требованием ни даже рекомендацией как таковой). Это один из подходов решения, при этом не самый лучший (со стороны гибкости), так как создает очень связанный код. Другими словами класс A никак не связана с классом B ни своим состоянием ни операциями над ними (как и класс B c А). Но вы принудительно вводите ДРУЖЕСТВЕННЫЕ функция которые должны знать о деталях реализации двух классов сразу. Появляется класс C и вы делаете все то же самое для каждого из классов A, B и С.
Рекомендованный подход - это чисто свободные функции (НЕ дружественные, а свободные). Да, придется выбирать - или создавать отдельную абстракцию через которую будет реализован доступ к данным (геттеры и сеттеры) или способ хранения данных набора классов (сторажи хранения) или делать публичные поля (что как бы для таких типов отражающих объекты/операции линейной алгебры как вектор, матрица и кватернионы - вполне общепринятое решение).
Кроме того, советую посмотреть на уже готовые реализации во многих библиотеках (если этот совет еще применим).
Некоторые из них отказались от реализации таких типов шаблонным параметром размера, а реализовали отдельно Vector2, Vector3, Vector4 (как и марицы и др). Так как не все из этих типов имеют обобщенные общепринятые операции (например GetX который есть у всех, и GetZ() - который у Vector4 (или более 4)).

Цитировать
У нас с вами разные вкусы. :) Мне не нравится, когда класс напичкан реализациями функций
Еще раз, речь идет только о шаблонных классах. Никакого явного выигрыша при отделение объявления методов от их реализации вы практически не получаете (тем более до С++11).
Шаблонные классы - это обобщенный код (для множества типов). Этот код должен быть максимально простым (и компактным) иначе читать его становится напорядок тяжелее чем  реализацию обычных (не шаблонных классов). В случае если вы разделяете описание и объявление методов, то кроме того, что вам приходится набирать больше текста (начиная от указания параметров шаблонного класса, до указания членом какого шаблонного класса с каким параметрами он является), вам нужно будет еще и постоянно удерживать контекст при просмотре (в голове) - что это за метод, к какому классу он относится (так как шаблонный класс может оказаться частично/или полностью специализирован и таких классов может быть уйма).
Близкий аналог такого "переключения" контекста для не шаблонного класса можно привести как - наследование. При просмотре тела метода без видения описания класса иногда возникает вопрос - а от кого этот класс наследуется, и если не помнишь то вынужден просмотреть описание класса.

Цитировать
Пользуясь случаем, также спрошу у вас один занятный вопрос: может вы знаете, зачем нужны замыкания функций? Я от современной функциональщины очень далёк (а от чтения руководства по Haskel остаётся недоумение, зачем и кому всё это нужно) и её просто не понимаю. Потому и не нахожу ни одной причины для использования замыкания и извращений с ним связанным в Си++.  :-\ Надуманные примеры я видел, но они именно что "а вот теперь мы можем и вот так". Ну, можем. А... зачем? :)

Если речь только про замыкания - то для того чтобы удерживая контекст вызвать обработку чего либо (любых переданных данных на обработку) с учетом того контекста который удерживаем.
То есть, вы принимаете решение что нужно сформировать/собрать "подходящий" контекст для обработки ожидаемых событий (событие может еще как не наступить или же уже наступило, что заставило вас формировать контекст). Дальше, по приходу события вы подготавливаете параметры либо же знаете кому можете делегировать формирование таких параметров. Ну и последний этап - отдаете на обработку "замыканию", которое знает как параметры обрабатывать с учетом удерживаемого ею контекста. Это так, упрощенно и своими словами.
Ближайший аналог - функторы (доступен с лохматых времен), объекты некого типа с перегруженной операцией operator().  Контекст ей может передаваться (такой функтор может как содержать внутри себя данные), а может не содержать (внутри функтора данные не содержатся).
Или же лямбды - более предпочтительнее чем функторы по ряду причин. Например потому что не требуют описания отдельного типа (что крайне многословно при использовании функторов). Умеют захватывать контекст автоматически, вдобавок поваляют выводить типы (auto и decltype) - что невероятно круто (относительно последнего), когда пишешь обработку обобщенную (а замыкание - это именно обработка и как правило используемая не однократно/обобщенно).


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: da-nie от Мая 25, 2018, 12:35:31 pm
Цитировать
Это не "стандартный" подход

Ну не знаю, я нигде не видел, чтобы от данного подхода отказывались в случае разнотипных классов в операторах.

Цитировать
Да, придется выбирать - или создавать отдельную абстракцию через которую будет реализован доступ к данным (геттеры и сеттеры) или способ хранения данных набора классов (сторажи хранения) или делать публичные поля (что как бы для таких типов отражающих объекты/операции линейной алгебры как вектор, матрица и кватернионы - вполне общепринятое решение).

А вот этого вот как раз и не хотелось бы. Все эти методы (публичные поля не в счёт) обязательно будут с проверкой корректности данных, а это не способствует скорости. Всё это запускаться может на достаточно слабых машинах, где и так-то система едва успевает обработать данные, а тут ещё и доступ к элементам дополнительно выполняет массу проверок.

Цитировать
Некоторые из них отказались от реализации таких типов шаблонным параметром размера,

 :D Это очень весело, пока не увидишь какой-нибудь фильтр Калмана с матрицами произвольного размера (который ещё и будут менять, так как процессор не справляется за заданное время), кучей векторов состояний и математикой с десяток листов, написанных не пограмистами, а математиками в их чудесном стиле. :)

Цитировать
Еще раз, речь идет только о шаблонных классах. Никакого явного выигрыша отделение объявления методов и их реализации вы практически не получаете

Да читаемость я получаю, читаемость. :) Ну вот текст я привёл - что, не понятно, что он делает? Понятно, разумеется. А засунь я всё это внутрь класса, попробуйте сходу отделите одну функцию от другой. При работе с классом нафиг не нужно знать его реализацию, а вот интерфейс нужен кровь из носу. Ну не помню, я как в матрице задать элемент - смотришь в описание класса и всё сразу понятно.

Спасибо за ответ. :)

Цитировать
Если речь только про замыкания - то для того чтобы удерживая контекст вызвать обработку чего либо (любых переданных данных на обработку) с учетом того контекста который удерживаем.

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

Цитировать
Ну и последний этап - отдаете на обработку "замыканию", которое знает как параметры обрабатывать с учетом удерживаемого ею контекста. Это так, упрощенно и своими словами.

А что мешает создать обычный объект с состоянием и работать с ним безо всякого замыкания, заполняя его нужными данными? Собственно, функтор таким объектом и будет. Тем не менее, почему же хочется не передавать явно контекст, а хочется, чтобы он сам передался? Что мешает заполнить вызываемую функцию нужными параметрами (ну или ссылками на них) и вызывать её для обработки?

Цитировать
а замыкание - это именно обработка и как правило используемая не однократно/обобщенно

А вот это вот не понял совсем.  :-\ Ведь любая функция - это обработка. Но не от любой требуется залазить во внешний, ей не передаваемый явно, контекст. ::)


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: lastcross от Мая 25, 2018, 01:04:50 pm
Цитировать
Да читаемость я получаю, читаемость. :)
Все это исключительно субъективная оценка (разумеется я и свою называю субъективной. Когда-то рассуждал именно как вы.. после пришел к другому подходу)

Цитировать
Вот только нафиг это нужно?
Ну самый ближайший пример - калбек события GUI который не позволяет вам через навязанный свой интерфейс передать произвольный объект. Но вы как пользователь считаете что корректная обработка может зависеть не только от параметров интерфейса калбека, но и от состояния отдельного объекта (связанного с окном, главным/родительским.. состоянием его контролов которые существуют независимо от контрола сгенерировавшего событие).

Код:
class MyFarme
{

bool CanApply(){}

void doApply(){}

///....

void Initialize()
{
  applyButton->Bind(BUTTON_PRESS_EVENT_ID, [this](EventButtonPress & event)
     {
       auto button = event->GetCtrl();
       if (this->CanApply())
       {
         doApply();
       }
     }
  );
}

};

Тут мы зарегистрировали событие обработки нажатия некой кнопки "Применить". Нажатие нашей системой GUI генерирует событие с калбеком
Код:
void OnButtonPress(EventButtonPress & event);
, где EventButtonPress - недоступный для изменения тип.

Объект MyFarme содержит внутри себя эту кнопку, и и имеет время жизни дольше чем сама кнопка. Обработка нажатой кнопки зависит от состояния MyFarme (результата CanApply). Как именно применять - также знает MyFarme (через doApply). Поэтому мы в качестве обработчика передаем лямбда функцию с замыканием (контекст this).
А теперь внимание вопрос - каким иным способом вы бы смогли точно также элегантно и немногословно реализовать такой обработчик?
(Напоминаю - система GUI-создана не вами и она навязывает способы обработки и интерфейсы событий. Изменения вы можете лишь вводить на уровне пользователя библиотеки, таких классов как MyFarme )


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: da-nie от Мая 25, 2018, 02:24:49 pm
Цитировать
Когда-то рассуждал именно как вы.. после пришел к другому подходу

Что же изменило ваше мнение? :)

Цитировать
Ну самый ближайший пример - калбек события GUI который не позволяет вам через навязанный свой интерфейс передать произвольный объект.

Вот тут сразу и возникает вопрос: я с GUI работал с WinAPI, с MFC, пару раз с Builder, с Photon в QNX. Что там происходит - GUI вызывает некую функцию, соответствующую событию. Скажем, нажали какую-то кнопку. О моей программе GUI не знает ничего, но это и нормально. Зачем же мне в эту функцию передавать какой-то ещё объект, если я могу этот объект сделать доступным в этой функции и так? Скажем, у меня будет некий глобальный класс-приложение (CMain), который является фасадом для всего остального. Я этот класс создам глобально и он в системе будет единственный глобальный элемент. В функции от GUI я просто сделаю extern CMain cMain и вызову cMain.PressButton(). А дальше CMain сделает всё, что нужно.

Цитировать
Поэтому мы в качестве обработчика передаем лямбда функцию с замыканием (контекст this).

Интересное решение. 8) Однако, непонятно, откуда этот самый this возьмётся. У GUI его точно нет. Значит, компилятор его прикладывает сам. Значит, для каждого объекта компилятор сам создал функцию обратного вызова, в которой сохранил this объекта, для которого она будет вызываться. Так?

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

Но чем в таком случае не устроил вариант с перенаправлением события в объект MyFarme?


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: lastcross от Мая 25, 2018, 07:56:34 pm
Цитировать
Что же изменило ваше мнение? :)

Достаточно небольшого опыта работы с шаблонами, чтобы понять - что обобщенный код нужно стараться не усложнять. В обобщенном коде важнее не набор интерфейсов, а понимание что он делает и как, что именно он обобщает. Если класс обобщенный (не специализирован) - то любая его специализация (полная или частичная) может полностью не только изменить его "интерфейс" но и "суть" (хотя интерфейс останется таким же). Вот вам пример: std::vector<T> и его частичная специализация std::vector<bool> - это не пример того как надо делать, а скорее пример того что специализация может полностью "перевернуть" структуру шаблонного класса.
Это приводит к тому, что для шаблонных классов крайне желательно видеть на одной странице не только "интерфейс" но и его содержание (весьма вероятно что при просмотре вы углубитесь более чем требовалось на первый взгляд, разве что это не стандартная хорошо известная библиотека).

Цитировать
Вот тут сразу и возникает вопрос: я с GUI работал с WinAPI, с MFC, пару раз с Builder, с Photon в QNX. Что там происходит - GUI вызывает некую функцию, соответствующую событию. Скажем, нажали какую-то кнопку. О моей программе GUI не знает ничего, но это и нормально. Зачем же мне в эту функцию передавать какой-то ещё объект, если я могу этот объект сделать доступным в этой функции и так?
А у вас все объекты глобальны? Или существуют разные копии одного и того же типа объектов? У вас окно в единственном экземпляре состоящие из одной кнопки? Или бывают еще панели которые в один момент времени могут существовать несколько штук? Что в таком случае вы будете делать в обработчике? Ведь this захватывается не спроста. Это означает что я допускаю существование нескольких экземпляров фреймов и они могут делать сугубо свою обработку (в зависимости от данных которыми владеют эти экземпляры, а не какое-то глобальное окно).

Цитировать
Интересное решение. 8) Однако, непонятно, откуда этот самый this возьмётся

Замыкание - это обобщенный термин. Я использовал лямбду, так как она короче и элегантнее в примере (это не единственные ее плюсы). Но замыкание можно реализовать через функциональный объект. В этом случае this - надо будет хранить явно. Но в любом случае - этот механизм позволяет инкапсулировать связи обработчика от кода вызывающий этот обработчик.
Да, для лямбды можете считать что компилятор сам создаст некий "функциональный объект" и осуществит захват тех параметров которые вы укажете. В случае с функциональным объектом - вам руками придется все это писать (но выбора у вас нет, если вы ниже С++11 - в этом случае только функциональные объекты или boost).

Цитировать
Но чем в таком случае не устроил вариант с перенаправлением события в объект MyFarme?

Тем что:
  • Использование глобального объекта внутри обработчика - не подходит. MyFarme - это дочерное окно, экземпляров которых может быть много. Единственный экземпляр окна не в состоянии обработать событие так как не знает от какого экземпляра окна MyFarme брать состояние.
  • Указание непосредственно в качестве обработчика экземпляра MyFarme со ссылкой на его метод обработки - не очень удобен и более многословен. Для начала, я бы попросил привести такой пример, чтобы точно точно прийти к пониманию что мы говорим про одно и тоже. Но даже без примера минусы (кроме многословности) - придется расширять сам класс, добавлять методы или менять интерфейс, вводить зависимости внутри хедера, между классами. Все это как минимум засоряет класс (помните свою жажду "читаемости" =) ), ну и кроме того - увеличивает время компиляции.

и др.

Можно взять еще како-либо пример который не связан с GUI
Код:

void DataStorage::doFilter(const Filter& filter)
{
  size_t count = 0;
  auto regectIt = std::remove_if(mData.begin(), mData.end(), [&filter, &count](const auto& element)

      return filter->Contains(count++, element);
   );
  mData.erase(regectIt , mData.end());
}


DataStorage - класс хранящий какие-то данные (контейнер). Метод doFilter фильтрует хранимые данные в соответствии с переданным фильтром filter типа Filter
Специфика интерфейса Filter::Contains  такова, что она принимает решения на основании передаваемых данных а также позиции хранимых данных (допустим некоторые фильтры исключительно фильтруют по позиции, а некоторые исключительно по содержимому, а третьи так вообще по тому и другому). Filter не знает как считать позиции это знает DataStorage. В свою очередь DataStorage не знает как фильтровать - это знает Filter (который был создан извне). алгоритм std::remove_if не умеет хранить счетчики и другие объекты, ему нужен функциональный объект или неxто чему он может применить вызов operator(). Такой оператор не содержится в Filter (так построен его интерфейс, и может он даже не доступен для модификаций). Но на примере удивительным образом все работает! Без особых усилий получилось связать те вещи которые не связывались и при этом не пришлось модифицировать (существенно) ни один из типов.
Мы сейчас не станем обсуждать, что можно было бы частично избежать всего этого путем банального явного цикла for по причине, что:
  • Явный цикл будет многословным и даже не эффективным, а при определенной реализации даже и опасным
  • Мы рассматриваем упрощенный пример. В реальных условиях предусловия захвата могут быть гораздо сложнее и одними циклами можно не отделатся



Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: da-nie от Мая 25, 2018, 08:41:24 pm
Цитировать
В обобщенном коде важнее не набор интерфейсов, а понимание что он делает и как, что именно он обобщает.

Но когда я пишу list<long> мне глубоко фиолетово, как там внутри это сделано - я туда внутрь даже смотреть не буду. И как бы так и должно быть для любых шаблонных классов. Для vector<bool> в данном случае я также не планирую заглядывать в реализацию. Да зачем бы мне это? Я загляну в описание библиотеки и там прочту о особенностях, подобной этой. Просто так быть не должно - это авторы совершенно напрасно сделали, нарушив принцип "знание принципов компенсирует недостаток фактов". Как и ожидалось, потеря унификации ни к чему хорошему не привела.

Цитировать
А у вас все объекты глобальны?

Нет, один. Он и является функцией main приложения по сути. Все остальные объекты живут внутри этого объекта.

Цитировать
У вас окно в единственном экземпляре состоящие из одной кнопки? Или бывают еще панели которые в один момент времени могут существовать несколько штук?

Внутри CMain могут существовать и классы панелей. Просто CMain знает, кому передать выполнение функции от интерфейса.

Цитировать
Это означает что я допускаю существование нескольких экземпляров фреймов и они могут делать сугубо свою обработку (в зависимости от данных которыми владеют эти экземпляры, а не какое-то глобальное окно).

Так даже и в MFC никто не мешает внутри главного класса окна создавать любые другие. При этом сообщения от интерфейса попадают в этот класс окна через карту сообщений. А дальше эти сообщения можно передать кому угодно.

Цитировать
Замыкание - это обобщенный термин.

Разумеется. Формально, даже вот этот глобальный cMain в функции обратного вызова является замыканием.

Цитировать
Но замыкание можно реализовать через функциональный объект. В этом случае this - надо будет хранить явно. Но в любом случае - этот механизм позволяет инкапсулировать связи обработчика от кода вызывающий этот обработчик.

Что-то мне подсказывает, что этот подход использован в каких-то новых фреймворках которых я не знаю (возможно, на C# - что-то много появилось программ на нём), и в тех, которые знаю я, он неприменим. Я не представляю, как к MFC или Qt, например, это вообще можно подключить. :) Вот в Win32API это может сработать - там функции обратного вызова задаются напрямую и очень было неудобно, что HWND присылается, а класс окна, который его и породил так просто не определить. Надо попробовать поиграться. :)

Цитировать
MyFarme - это дочерное окно, экземпляров которых может быть много. Единственный экземпляр окна не в состоянии обработать событие так как не знает от какого экземпляра окна MyFarme брать состояние.

Да, так, конечно, удобно. :) Это не требует сопоставления HWND и класса.

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

Я имел в виду, вышеописанный метод с глобальным объектом MyFrame вместо CMain. В функции обратного вызова, разумеется, функцию класса записать нельзя.

Цитировать
В свою очередь DataStorage не знает как фильтровать - это знает Filter (который был создан извне).

То есть, всё это нужно только в том случае, когда хочется навесить новую функциональность на уже существующую, не меняя реализацию старой?


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: lastcross от Мая 25, 2018, 11:39:27 pm
Цитировать
Но когда я пишу list<long> мне глубоко фиолетово
По этому я и отметил - субъективно это. Мой опыт привел меня именно к своему выбору. У вас же свой опыт ).

Цитировать
Внутри CMain могут существовать и классы панелей. Просто CMain знает, кому передать выполнение функции от интерфейса.
В примере, он не может знать какому из объектов адресовать событие. Поэтому адресовать калбек к вашему объекту - некорректно.

Цитировать
Так даже и в MFC никто не мешает внутри главного класса окна создавать любые другие. При этом сообщения от интерфейса попадают в этот класс окна через карту сообщений. А дальше эти сообщения можно передать кому угодно.

Это потому что вы привязаны к такому механизму событий. Это было популярно в 90-е. На дворе 21 век. Замыкание позволяют избежать ситуации с двойной диспечерезацией (когда нужно передавать посреднику, который должен знать о всех обработчиках).
В Qt - есть свои механизмы сигнал-слот (https://wiki.qt.io/New_Signal_Slot_Syntax/ru), построенный по схожему принципу. wxWidgets - по схожему принципу (http://wxwidgets.blogspot.com/2013/08/wxwidgets-and-c-11.html). Начиная с ++11 - большинство gui-библиотек переходят на схожий механизм, потому как это стало доступнее и практически дешево.

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


Цитировать
Я имел в виду, вышеописанный метод с глобальным объектом MyFrame вместо CMain. В функции обратного вызова, разумеется, функцию класса записать нельзя.
Почему же? Можно. Через std::bind (http://ru.cppreference.com/w/cpp/utility/functional/bind) в связке std::function (http://ru.cppreference.com/w/cpp/utility/functional/function) (опять же в терминах С++11) или одноименными аналогами из boost::bind (https://www.boost.org/doc/libs/1_64_0/libs/bind/doc/html/bind.html) и boost::function (https://www.boost.org/doc/libs/1_64_0/doc/html/function/tutorial.html)(для до С++11)

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

Еще один из примеров - некий метод должен рекурсивно что-то обойти и посчитать. Как известно, для рекурсивного обхода нужен метод входа, и метод рекурсивной операции перехода по итерациям (собственно обход). Таких методов может быть несколько (рекурсивно в зависимости от направления и критериев остановки/поиска). Заводить специальные методы не всегда нужно. Если учесть что лишь некоторые операции требуют такой рекурсии, то благодаря лямбдам можно не объявлять отдельные методы переходов (обходов), а реализовать их непосредственно внутри конкретных методов входа. Такие лямбды захватывают как условия выхода, счетчики, так и самих себя для возможности рекурсивно вызываться.

Надеюсь хотя бы малость мне удалось раскрыть "тайну использования" замыканий =)


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: da-nie от Мая 26, 2018, 07:21:39 am
Цитировать
В примере, он не может знать какому из объектов адресовать событие. Поэтому адресовать калбек к вашему объекту - некорректно.

Что-то я с таким не сталкивался. Если у меня есть форма, то я всегда знаю, от какого элемента и для кого будет это сообщение. Если же форма создаётся динамически, то элемент можно найти по его идентификатору/дескриптору.

Цитировать
На дворе 21 век.

Вот только на запрос "в чём написать графическое приложение для Windows для C++" ответ в поисковиках почему-то всё тот же MFC и Qt. ::) А запрос про применение замыканий приводит практически всегда к web-технологиям.

Цитировать
В Qt - есть свои механизмы сигнал-слот, построенный по схожему принципу.

А, ну до Qt5 я не дошёл. :)

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

Это несомненно. :)

Цитировать
Почему же? Можно. Через std::bind в связке std::function

Как я понимаю,  это такая же подмена истинной функции обратного вызова на нечто скрытое, создающееся компилятором с дополнительной информацией об объекте.
Кстати, по поводу functional.
То ли я что-то не понял, то ли VC2010 с functional работает странно. Вот я взял код из примера:
Код:
auto lambda_in=[](int x)
 {
  return([=](int y) {return(x+y);});
 };

 auto lambda_out=[](const function<int(int)>& f,int z)
 {
  return(f(z)*2);
 };
 auto answer=lambda_out(lambda_in(7),8);
Пример понятен (кроме const function<int(int)> - что за странная запись int(int)?).
Всё это студия компилирует вот так:

Цитировать
1>main.cpp(39): error C2664: 'int `anonymous-namespace'::<lambda2>::operator ()(const std::tr1::function<_Fty> &,int) const' : cannot convert parameter 1 from 'void' to 'const std::tr1::function<_Fty> &'
1>          with
1>          [
1>              _Fty=int (int)
1>          ]
1>          Expressions of type void cannot be converted to other types
1>main.cpp(39): fatal error C1903: unable to recover from previous error(s); stopping compilation
1>
1>Build FAILED.

Цитировать
Надеюсь хотя бы малость мне удалось раскрыть "тайну использования" замыканий =)

Да, спасибо за информацию. :) К сожалению, я не знаю абсолютно никого, кто бы знал для чего всё это нужно и как этим пользоваться на практике. Поиск же в инете приводит к вороху бесполезных статей (как и в случае с unit-тестами). :)


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: lastcross от Мая 26, 2018, 01:34:57 pm
Цитировать
Что-то я с таким не сталкивался. Если у меня есть форма, то я всегда знаю, от какого элемента и для кого будет это сообщение. Если же форма создаётся динамически, то элемент можно найти по его идентификатору/дескриптору.

Представим такую иерархию владения: MainWnd->UseForms->SelectorForm->Fields->SomeButton
Те что слева содержат тех что справа, при это типы окон (контролов) справа могут существовать не в единственно экземпляре (вообразите такой сложный продукт уровня Photoshop или IDE). Дальше возможна ситуация, когда конкретную кнопку SomeButton нужно обработать в соответствии с состоянием контрола который ею владеет (непсредственого владельца). Я так понимаю что вы предлагаете связывать обработчик с единственным экземпляром MainWnd. Допустим GUI система в связке со своей системой событий предоставляет идентификатор окна от которого пришло событие (хотя это не обязательно должно быть в общем случае - мы ведь не только рассматриваем GUI, а вообще концепцию передачи сообщений некой системе и ее обработки). Что будет делать MainWnd обработчик? Как он сопоставит по Handle-окна конкретный экземпляр Fields среди нескольких? Как вы приведете вообще это окно к типу Fields, чтобы начать делегирование обработки события? Вы набросайте это конструкцию и по-моему сразу станет все очевидно, где краткость и ясность - а где лишние телодвижения, лес в котором можно заблудится и нагородить ошибок.
Вдобавок, я не отметил тот факт - что замыкания так же используются для передачи не только ссылок на объект хранимый состояния, но и копии состояний. Это значит что на момент регистрации обработчика мы знаем с каким контекстом надо обрабатывать событие. То есть контекст обработки важен на момент регистрации, а не в момент создания события(связь окон с потоками, где окно может умереть раньше чем начать обрабатываться сам поток). Все это благодаря захвату с копированием. Даже на примере синхронного вызова - создаем множество кнопок, по нажатию которых выполнятся операции с выбранным файлом. Основываясь на патернах Command, для каждого обработчика нажатия кнопки захватываем по копии созданый объект команд. Все что нужно в обработчике - просто исполнить команду. Никакой явной диспечерезации в коде и размазанной логики (проверки что за кнопка - как соотнести ее с командой, где хранить/откуда получить дескриптор выбранного файла и т.д.)

Цитировать
Как я понимаю,  это такая же подмена истинной функции обратного вызова на нечто скрытое, создающееся компилятором с дополнительной информацией об объекте.
Почему скрытое? Это полноценный функциональный объект, который ведет себя как функция но способен хранить дополнительные параметры требуемые функции. Любда - вот это "мистика" создаваемая компилятором, так как некоторые механизмы скрываются на этапе компиляции (тип лямбды, ее расположение в коде и подобное). Функциональный объект он же как все объекты.

Цитировать
Кстати, по поводу functional.
То ли я что-то не понял, то ли VC2010 с functional работает странно. Вот я взял код из примера:
....
Всё это студия компилирует вот так:
...

А попробуйте вот так (http://coliru.stacked-crooked.com/a/f95d4cda6f26b8bb)
Основная причина - ограничение стандарта ++11. В отличии от ++14 (вот пример (http://coliru.stacked-crooked.com/a/340fca149c51132f)), лямбда в ++11 не умеет автоматически выводить тип для своих аргументов (ну или умеет с ограничениями). Это означает, что недостаточно просто передать в место функтора лямбду. Лямбду надо преобразовать явно. То есть построить функтор на основе лямбды и передать

Цитировать
Пример понятен (кроме const function<int(int)> - что за странная запись int(int)?).
Что расположено до круглых скобочек - тип возвращаемого значения. Что внутри типы параметров. Про это можно почитать в документации  - ссылку я давал выше


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: da-nie от Мая 26, 2018, 05:09:51 pm
Цитировать
справа могут существовать не в единственно экземпляре (вообразите такой сложный продукт уровня Photoshop или IDE).

Так это всё решается механизмом диспетчеризации. Да, он будет сложным.

Цитировать
Дальше возможна ситуация, когда конкретную кнопку SomeButton нужно обработать в соответствии с состоянием контрола который ею владеет (непсредственого владельца).

Да я не спорю, что так гораздо удобнее. Проблема только в том, что непосредственное подключение функций обратного вызова, вообще говоря, достаточно низкоуровневая часть, которую обычно скрывают. В том же photon я могу назначить обработчик, но это будет далеко не лямбда. В результате возникает вопрос - что нужно взять (кроме Qt5), чтобы это  применять на практике. Вот на чём сейчас десктопные приложения пишут (ну, кроме net)? Я не знаю. Вот запускаю я DrWeb - на чём написан его интерфейс? Без понятия.

Цитировать
Почему скрытое?

Потому что на уровне языка происходит магия - GUI, который не знает ничего, вызывает некую функцию, которая магическим образом сопоставляет именно вот это вызов именно с тем классом, для которого он был зарегистрирован (при этом GUI при регистрации получил обычную функцию, а что её надо перенаправить с дополнительной информацией знает только компилятор).

Цитировать
А попробуйте вот так

Нет, так тоже не хочет. Ни основной, ни альтернативный. "1>main.cpp(46): error C2440: 'static_cast' : cannot convert from 'void' to 'InFunction_t'".
Но на самом деле, я даже не знаю, установлен у меня патч для Си++ 11 или нет. Я его сам точно не ставил. Я даже не помню, откуда у меня данный дистрибутив студии. Просто попробовал некоторые операторы и они заработали. Но они могут быть реализованы и до появления стандарта.

Цитировать
Что расположено до круглых скобочек - тип возвращаемого значения. Что внутри типы параметров

А, понятно. :) Это мне в голову не пришло.
Хотя непонятно, как такой шаблон может существовать. Ведь это же параметр. Разве можно сделать так: vector<int(int)>? Нельзя - непонятно, что это. А function<int(int)> создать можно. Каким образом так получается-то?


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: lastcross от Мая 26, 2018, 05:27:16 pm
Цитировать
Так это всё решается механизмом диспетчеризации. Да, он будет сложным.
О чем и речь! И не просто сложным, а через чур сложным - с построением иерархии наследования и обилием кастования.

Цитировать
Да я не спорю, что так гораздо удобнее. Проблема только в том, что непосредственное подключение функций обратного вызова, вообще говоря, достаточно низкоуровневая часть, которую обычно скрывают.

Берите связку boost::function и boost::bind пишите свои функторы и без ++11 уже можете передать в куда угодно свой кастомный объект с захватом вместо привычного всеми калбек методов.

Цитировать
Потому что на уровне языка происходит магия - GUI, который не знает ничего, вызывает некую функцию, которая магическим образом сопоставляет именно вот это вызов именно с тем классом, для которого он был зарегистрирован (при этом GUI при регистрации получил обычную функцию, а что её надо перенаправить с дополнительной информацией знает только компилятор).

Это магия называется operator() и она не такая уж магия (компилятор за вас ее не строит). А вот с лямбдой дело стоит иначе - компилятор за вас формирует истинный тип лямбды - вы даже его получить не можете в явном виде.

Цитировать
Нет, так тоже не хочет. Ни основной, ни альтернативный. "1>main.cpp(46): error C2440: 'static_cast' : cannot convert from 'void' to 'InFunction_t'".
Но на самом деле, я даже не знаю, установлен у меня патч для Си++ 11 или нет. Я его сам точно не ставил. Я даже не помню, откуда у меня данный дистрибутив студии. Просто попробовал некоторые операторы и они заработали.
Скорее всего у вас не поддерживается ++11

Цитировать
Каким образом так получается-то?

Ну а тут магия использование средств ++11 и макросов.


Название: Re: Нужна помощь. Ошибка QNX Momentix при компиляции
Отправлено: da-nie от Мая 26, 2018, 07:26:05 pm
Цитировать
О чем и речь! И не просто сложным, а через чур сложным - с построением иерархии наследования и обилием кастования.

Да нет, просто каждый класс наделяется списком того, чем он владеет. А дальше обычная диспетчеризация по маршруту графа с опросом "это твоё?" и остановкой, когда найден владелец. На это можно пойти в GUI, так как в 99.9999999999% случаев скорость реакции это не снизит никак. В конце концов, как же писалось всё то ПО до С++ 11?

Цитировать
Берите связку boost::function и boost::bind пишите свои функторы и без ++11 уже можете передать в куда угодно свой кастомный объект с захватом вместо привычного всеми калбек методов.

С boost я не знаком вовсе (и насколько я слышал, там что-то очень монструозное). :) Но я о чём речь-то веду? Привязка функции обратного вызова в GUI библиотеках является низким уровнем, до которого пользователь, обычно, не допускается. В той же MFC всё это скрыто. Я не могу переопределить в MFC функцию окна оставаясь в MFC - мне для этого придётся регистрировать свой класс окна со всеми вытекающими.

Цитировать
А вот с лямбдой дело стоит иначе

Так мы о лямбда-функциях и говорим. У вас в примере они и есть.