Страниц: [1] 2
  Печать  
Автор Тема: Нужна помощь. Ошибка QNX Momentix при компиляции  (Прочитано 7355 раз)
DavASko
Участник
*
Offline Offline

Сообщений: 3


Просмотр профиля
« : Сентября 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 разные машины, но ошибка совершенно та же.
Подскажите мне пожалуйста как можно решить эту проблему. Уже неделю не могу проект собрать.
Записан
BrutNemo
Участник
*
Offline Offline

Сообщений: 26


Просмотр профиля
« Ответ #1 : Сентября 17, 2013, 08:47:32 am »

не уверен..., но с
Цитировать
c:/QNX632/ide4-workspace/cnc/src/ECM_machine/x86/o-g/machine_g.res
снимите флажок 'Только чтение'
Записан
DavASko
Участник
*
Offline Offline

Сообщений: 3


Просмотр профиля
« Ответ #2 : Сентября 17, 2013, 10:18:31 am »

Это пробовал до этого, даже по всякому комбинировал, но, к сожалению, ничего не помогло Sad
Записан
BrutNemo
Участник
*
Offline Offline

Сообщений: 26


Просмотр профиля
« Ответ #3 : Сентября 17, 2013, 10:49:52 am »

снимите флажок 'Только чтение' + запустите Momentics от имени администратора
Записан
DavASko
Участник
*
Offline Offline

Сообщений: 3


Просмотр профиля
« Ответ #4 : Сентября 19, 2013, 08:14:46 am »

Флажки не помогли.
Пмогла конфигурация make файла, а вернее конкретное описание пути для билда проекта......ю начиная из корневого каталога и до самой папки. Проект скомпилил, всем спасибо, кто попытался помочь.
Записан
da-nie
Full Member
***
Offline Offline

Сообщений: 211



Просмотр профиля
« Ответ #5 : Мая 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 и такой же оператор - получится кольцо.
« Последнее редактирование: Мая 22, 2018, 09:36:03 pm от da-nie » Записан

И день и ночь в пути
A_O
Full Member
***
Offline Offline

Сообщений: 212


Просмотр профиля
« Ответ #6 : Мая 23, 2018, 09:52:26 am »

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

Сообщений: 211



Просмотр профиля
« Ответ #7 : Мая 23, 2018, 09:57:49 am »

Так #pragma once не избавит от включения #include друг-друга в классах.  Roll Eyes
Записан

И день и ночь в пути
A_O
Full Member
***
Offline Offline

Сообщений: 212


Просмотр профиля
« Ответ #8 : Мая 23, 2018, 03:56:28 pm »

Так #pragma once не избавит от включения #include друг-друга в классах.  Roll Eyes
И на здоровье. Бесконечной петли не будет.
Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 234


Просмотр профиля
« Ответ #9 : Мая 23, 2018, 06:44:51 pm »

Чего-то я сегодня не понял, что за фигня.

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

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

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

Сообщений: 234


Просмотр профиля
« Ответ #10 : Мая 23, 2018, 07:03:56 pm »

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

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

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

Сообщений: 211



Просмотр профиля
« Ответ #11 : Мая 23, 2018, 08:08:03 pm »

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

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

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

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

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

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

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

Так криво же.

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

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

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

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

Цитировать
constexpr

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

И день и ночь в пути
da-nie
Full Member
***
Offline Offline

Сообщений: 211



Просмотр профиля
« Ответ #12 : Мая 23, 2018, 08:43:27 pm »

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

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

Прикольно.  Undecided

Возвращаясь к шаблонам. Всё-таки, как в QNX правильно и студия 2010 это приняла. Правда, иным образом. Вот тут написано.
Цитировать
...
Если Вам кажется, что объявление в классе и определение вне его должны быть как-то связаны, то это не так. Это две совершенно разные функции(одна шаблонная, а другая нет), а т.к., согласно 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.

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

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

Код:
#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 не потребовалось делать предварительное описание.  Roll Eyes
« Последнее редактирование: Мая 23, 2018, 10:00:15 pm от da-nie » Записан

И день и ночь в пути
lastcross
Full Member
***
Offline Offline

Сообщений: 234


Просмотр профиля
« Ответ #13 : Мая 24, 2018, 09:01:14 pm »

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

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


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

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

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

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

Записан
da-nie
Full Member
***
Offline Offline

Сообщений: 211



Просмотр профиля
« Ответ #14 : Мая 24, 2018, 09:41:09 pm »

Цитировать
Именно по этому я и намекал, что френды скорее всего вам не нужны.

Так это стандартный подход. Undecided

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

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

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

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

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

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

Пользуясь случаем, также спрошу у вас один занятный вопрос: может вы знаете, зачем нужны замыкания функций? Я от современной функциональщины очень далёк (а от чтения руководства по Haskel остаётся недоумение, зачем и кому всё это нужно) и её просто не понимаю. Потому и не нахожу ни одной причины для использования замыкания и извращений с ним связанным в Си++.  Undecided Надуманные примеры я видел, но они именно что "а вот теперь мы можем и вот так". Ну, можем. А... зачем? Smiley
« Последнее редактирование: Мая 24, 2018, 09:50:38 pm от da-nie » Записан

И день и ночь в пути
Страниц: [1] 2
  Печать  
 
Перейти в: