Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > [C++] Инициализация класса матрицы


Автор: JackYF 29.11.2007, 18:45
Итак, реализуется свой велосипедный класс "матрица" для сдачи лабы.

Вопрос в следующем: я хочу, чтобы матрица умела инициализироваться двумерным заданным массивом наподобие:
Код

int m[2][3] = { {1, 2, 3}, {4, 5, 6} };


Класс шаблонный, единственный параметр шаблона - тип.
Конструктор
Код

standart_matrix(T** values, size_t rows, size_t columns);


справедливо не срабатывает, так как int[2][3] не приводится к int**, у него другая физ. структура.

Возможные видимые мной выходы: 

1. cделать конструктор
Код

standart_matrix(void* values, size_t rows, size_t columns);

К нему обращаться через
Код

//...
standart_matrix matrix(reinterpret_cast<void*>(m), 2, 3);


2.  Сделать конструктор шаблонным, типа
Код

template <size_t columns>
standart_matrix(T values[][columns], size_t rows);


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

Кто какой вариант предпочёл бы? Или предложите свой.

Автор: archimed7592 29.11.2007, 19:24
Цитата(JackYF @  29.11.2007,  18:45 Найти цитируемый пост)
Вопрос в следующем: я хочу, чтобы матрица умела инициализироваться двумерным заданным массивом наподобие:

Жди С++09 - возможно туда включат initializer lists smile.


Цитата(JackYF @  29.11.2007,  18:45 Найти цитируемый пост)
int m[2][3] = { {1, 2, 3}, {4, 5, 6} };

Давай, для начала, разберёмся с этим: ты хочешь параметры конструктора size_t rows и size_t columns передавать таким образом(через "квадратные скобочки")?

Можешь написать как ты хочешь, чтобы выглядела инициализация(примерно, но без таких ляпов)?

Автор: JackYF 29.11.2007, 19:32
Цитата(archimed7592 @  29.11.2007,  19:24 Найти цитируемый пост)
Давай, для начала, разберёмся с этим: ты хочешь параметры конструктора size_t rows и size_t columns передавать таким образом(через "квадратные скобочки")?

Можешь написать как ты хочешь, чтобы выглядела инициализация(примерно, но без таких ляпов)?

Эээ... не понял, объясни, в чём ляп.

Ну, в идеальном случае так:
Код

standart_matrix matrix(m, 2, 3);
// вместо 2,3 здесь можно подставить sizeof(...)/sizeof(...) и т.д...


Добавлено через 2 минуты и 38 секунд
Цитата(archimed7592 @  29.11.2007,  19:24 Найти цитируемый пост)
Жди С++09 - возможно туда включат initializer lists

Жду. Только вот лабу через 2 недели сдавать smile

Автор: archimed7592 29.11.2007, 19:50
Цитата(JackYF @  29.11.2007,  19:32 Найти цитируемый пост)
Эээ... не понял, объясни, в чём ляп.


Цитата(JackYF @  29.11.2007,  18:45 Найти цитируемый пост)
Вопрос в следующем: я хочу, чтобы матрица умела инициализироваться двумерным заданным массивом наподобие:


Цитата(JackYF @  29.11.2007,  18:45 Найти цитируемый пост)
int m[2][3]

Видишь ли, в языке С++ так массивы делают smile. Т.е. это будет как минимум массив матриц...

Автор: JackYF 29.11.2007, 20:07
Цитата(archimed7592 @  29.11.2007,  19:50 Найти цитируемый пост)
Т.е. это будет как минимум массив матриц... 


archimed7592, ты чего?
у меня два измерения - строки, столбцы. Где массив матриц-то?

Автор: archimed7592 29.11.2007, 20:25
Ытить... Посыпаю голову пеплом. Спать уже пора smile.


Цитата(JackYF @  29.11.2007,  18:45 Найти цитируемый пост)
Кто какой вариант предпочёл бы?

Второй.
Во-первых, с вероятностью 80% эти ф-ции заинлайнятся. Особенно, если весь конструктор будет представлять из себя forwarder на какой-нибудь.
Во-вторых, даже если бинарник разрастётся, то ты этого не заметишь(ну что такое на сегодняшний день 100 кб?) smile.
В-третьих - это лаба smile.

Автор: JackYF 29.11.2007, 20:32
Цитата(archimed7592 @  29.11.2007,  20:25 Найти цитируемый пост)
Особенно, если весь конструктор будет представлять из себя forwarder на какой-нибудь.

Да, так и есть.

Что ж, позиция ясна. Со всем согласен, поэтому пока остановлюсь тоже на варианте 2, как рабочем.
Тему пока не закрываю, может, ещё кто высказаться захочет.

Автор: archimed7592 29.11.2007, 20:37
За первый вариант вряд ли кто выскажется smile.
smile

Автор: bsa 29.11.2007, 21:51
или я что-то не понял, или у меня крутой компилятор:
Код
#include <iostream>
template<typename T>
class Matrix
{
public:
        template<int m, int n>
        Matrix(const T (&values)[m][n]){
                std::cout << m << "," << n << std::endl;
                for(int i = 0; i < m; ++i) {
                        for(int j = 0; j < n; ++j)
                                std::cout << values[i][j] << " ";
                        std::cout << std::endl;
                }
        }
};

int main()
{
        int x[2][3] = { {1, 2, 3}, {4, 5, 6} };
        Matrix<int> t(x);
        return 0;
}

Автор: JackYF 29.11.2007, 22:12
Цитата(bsa @  29.11.2007,  21:51 Найти цитируемый пост)
template<int m, int n>
        Matrix(const T (&values)[m][n]){

Правильно. Это развитие второго варианта, шаблонный конструктор. Только уже с двумя параметрами smile

Автор: JackYF 29.11.2007, 22:55
Так. Теперь меня удивляет компилятор... g++ 4.2.1

Здесь идут части одного .hpp-файла, который инклюдится в один .cpp
Сначала часть-"заголовок":
Код

template < typename T >                                                                                                                              
        class standart_matrix                                                                                                                                
        {                                                                                                                                                    
         private:                                                                                                                                            
            typedef standart_matrix<T> self;                                                                                                                 
                                                                                                                                                             
            size_t __rows;                                                                                                                                   
            size_t __columns;                                                                                                                                
             T* __storage;                                                                                                                                    
                                                                                                                                                             
         protected:                                                                                                                                          
            ulong _smp_to_storage_pos(const matrix_position& smp) const;                                                                                     
            void _verify_sizes(const self& other) const;                                                                                                     
                                                                                                                                                             
            void _ctor(size_t rows, size_t columns);                                                                                                         
            void _ctor(const self& other);                                                                                                                   
            void _dtor();                                                                                                                                    
         public:                                                                                                                                             
            typedef matrix_position smp;                                                                                                                     
            typedef size_t size_type;                                                                                                                        
                                                                                                                                                             
            standart_matrix(size_t rows, size_t columns);                                                                                                    
            template < size_t rows, size_t columns >                                                                                                         
            standart_matrix(const T (&values)[rows][columns]);                                                                                               
            standart_matrix(const self& other);                                                                                                              
            self& operator=(const self& other);                                                                                                              
                                                                                                                                                             
            template < size_t rows, size_t columns >                                                                                                         
            void assign(const T (&values)[rows][columns]);                                                                                                   
                                                                                                                                                             
            T& operator[](const smp& index );                                                                                                                
            const T& operator[](const smp& index) const;                                                                                                     
            void set(const smp& index, const T& value);                                                                                                      
            const T& get(const smp& index) const;                                                                                                            
                                                                                                                                                             
            standart_matrix<T>& operator+=(const standart_matrix<T>& other);                                                                                 
            standart_matrix<T>& operator-=(const standart_matrix<T>& other);                                                                                 
            standart_matrix<T>& operator*=(const standart_matrix<T>& other);                                                                                 
                                                                                                                                                             
            const self operator-() const;
            
            size_t rows() const;                                                                                                                             
            size_t columns() const;                                                                                                                          
                                                                                                                                                             
            virtual ~standart_matrix();                                                                                                                      
                                                                                                                                                             
            const standart_matrix<T> operator+(const standart_matrix<T>& other) const;                                                                       
            const standart_matrix<T> operator-(const standart_matrix<T>& other) const;                                                                       
            const standart_matrix<T> operator*(const standart_matrix<T>& other) const;                                                                       
                                                                                                                                                             
            bool operator==(const standart_matrix<T>& other) const;                                                                                          
            bool operator!=(const standart_matrix<T>& other) const;                                                                            


Затем один из методов:
Код

template < size_t rows, size_t columns >                                                                                                             
template < typename T >                                                                                                                              
standart_matrix<T>::standart_matrix(const T (&values)[rows][columns])                                                                                
{                                                                                                                                                    
     _ctor(rows, columns);                                                                                                                            
     // тут должно быть код, но пока его нет...                                            
}  


Ругается компилятор так:
Цитата

/home/jackyf/Work/Programming/linux/yfLibrary/workcopy-linux/yf/math/standart_matrix.hpp:158: error: invalid use of incomplete type ‘class yf::math::standart_matrix<T>’
/home/jackyf/Work/Programming/linux/yfLibrary/workcopy-linux/yf/math/standart_matrix.hpp:43: error: declaration of ‘class yf::math::standart_matrix<T>’

Без этого самого метода всё чики-пики. Вопрос - почему компилятор считает, что класс неполон?  smile 

Автор: MAKCim 29.11.2007, 23:05
Код

template < class T > 
template < size_t rows, size_t columns >                                                                                                                                                                                                                             
standart_matrix<T>::standart_matrix(const T (&values)[rows][columns])                                                                                
{                                                                                                                                                    
     _ctor(rows, columns);                                                                                                                            
     // тут должно быть код, но пока его нет...                                            
}  

Автор: bsa 29.11.2007, 23:09
А если 
Код
template < size_t rows, size_t columns >
template < typename T >
заменить на:
Код
template <typename T, size_t rows, size_t columns>

Автор: JackYF 29.11.2007, 23:10
MAKCim, да, было такое подозрение.

На это компилятор говорит, что
Цитата

/home/jackyf/Work/Programming/linux/yfLibrary/workcopy-linux/yf/math/standart_matrix.hpp:158: error: prototype for ‘yf::math::standart_matrix<T>::standart_matrix(const T (&)[rows][columns])’ does not match any in class ‘yf::math::standart_matrix<T>’

И пока не поменяешь обратно порядок template'ов, говорит о несоответствии прототипов.

Добавлено через 1 минуту и 41 секунду
bsa, аналогично с вариантом MAKCimа. На прототипы начинает ругаться.

Добавлено через 2 минуты и 38 секунд
Вариант
Код

template <size_t rows, size_t columns, typename T >

На прототипы не ругается, но выдаёт ошибку про "imcomplete type".

Добавлено через 8 минут и 18 секунд
Сужаем ошибку. За основу взял пример bsa:

Код

#include <iostream>                                                                                                                                          
template<typename T>                                                                                                                                         
class Matrix                                                                                                                                                 
{                                                                                                                                                            
    public:                                                                                                                                                  
        template<int m, int n>                                                                                                                               
        Matrix(const T (&values)[m][n]);                                                                                                                     
};                                                                                                                                                           
                                                                                                                                                             
template<int m, int n>                                                                                                                                       
template<typename T>                                                                                                                                         
Matrix<T>::Matrix(const T (&values)[m][n])                                                                                                                   
{                                                                                                                                                            
    std::cout << m << "," << n << std::endl;                                                                                                                 
    for (int i = 0; i < m; ++i)                                                                                                                              
    {                                                                                                                                                        
        for (int j = 0; j < n; ++j)                                                                                                                          
        {                                                                                                                                                    
            std::cout << values[i][j] << " ";                                                                                                                
        }                                                                                                                                                    
        std::cout << std::endl;                                                                                                                              
    }                                                                                                                                                        
}                                                                                                                                                            
                                                                                                                                                             
int main()                                                                                                                                                   
{                                                                                                                                                            
    int x[2][3] = { {1, 2, 3}, {4, 5, 6} };                                                                                                                  
    Matrix<int> t(x);                                                                                                                                        
    return 0;                                                                                                                                                
}                      

Цитата

main.cpp:12: error: invalid use of incomplete type ‘class Matrix<T>’
main.cpp:4: error: declaration of ‘class Matrix<T>’


Итого имеем то же самое.

Автор: bsa 29.11.2007, 23:44
попробуй определить конструктор в теле класса. Если, конечно, на принцип не пошел...

Автор: JackYF 30.11.2007, 00:17
Буквально сейчас об этом подумал. Как воркэраунд попробую сделать.
...
Блин, что за ёлки...
опять ему что-то не так:
Код

template < typename T >                                                                                                                              
        class standart_matrix                                                                                                                                
        {                                                                                                                                                    
         private:                                                                                                                                            
            typedef standart_matrix<T> self;                                                                                                                 
                                                                                                                                                             
            size_t __rows;                                                                                                                                   
            size_t __columns;                                                                                                                                
            T* __storage;                                                                                                                                    
                                                                                                                                                             
         protected:                                                                                                                                          
            ulong _smp_to_storage_pos(const matrix_position& smp) const;                                                                                     
            void _verify_sizes(const self& other) const;                                                                                                     
                                                                                                                                                             
            void _ctor(size_t rows, size_t columns);                                                                                                         
            void _ctor(const self& other);                                                                                                                   
            void _dtor();                                                                                                                                    
         public:                                                                                                                                             
            typedef matrix_position smp;                                                                                                                     
            typedef size_t size_type;                                                                                                                        
                                                                                                                                                             
            standart_matrix(size_t rows, size_t columns);                                                                                                    
                                                                                                                                                             
            template < size_t rows, size_t columns >                                                                                                         
            standart_matrix(const T (&values)[rows][columns])                                                                                                
            {                                                                                                                                                
                _ctor(rows, columns);                                                                                                                        
                //this->assign(values);                                                                                                                      
            }                                                                                                                                                
                                                                                                                                                             
            standart_matrix(const self& other);                                                                                                              
            self& operator=(const self& other);template < size_t rows, size_t columns >                                                                                                         
            void assign(const T (&values)[rows][columns])                                                                                                    
            {                                                                                                                                                
                _dtor();                                                                                                                                     
                _ctor(rows, columns);                                                                                                                        
                for (size_t i = 0; i < __rows; ++i)                                                                                                          
                {                                                                                                                                            
                    for (size_t j = 0; j < __columns; ++j)                                                                                                   
                    {                                                                                                                                        
                        this->set(smp(i,j), values[i][j]);                                                                                                   
                    }                                                                                                                                        
                }                                                                                                                                            
            }                                                                                                                                                
                                                                                                                                                             
            T& operator[](const smp& index );                                                                                                                
            const T& operator[](const smp& index) const;                                                                                                     
            void set(const smp& index, const T& value);                                                                                                      
            const T& get(const smp& index) const;                                                                                                            
                                                                                                                                                             
            standart_matrix<T>& operator+=(const standart_matrix<T>& other);                                                                                 
            standart_matrix<T>& operator-=(const standart_matrix<T>& other);                                                                                 
            standart_matrix<T>& operator*=(const standart_matrix<T>& other);                                                                                 
                                                                                                                                                             
            const self operator-() const;                                                                                                                    
                                                                                                                                                             
            size_t rows() const;                                                                                                                             
            size_t columns() const;                                                                                                                          
                                                                                                                                                             
            virtual ~standart_matrix();                                                                                                                      
                                                                                                                                                             
            const standart_matrix<T> operator+(const standart_matrix<T>& other) const;                                                                       
            const standart_matrix<T> operator-(const standart_matrix<T>& other) const;                                                                       
            const standart_matrix<T> operator*(const standart_matrix<T>& other) const;                                                                       
                                                                                                                                                             
            bool operator==(const standart_matrix<T>& other) const;                                                                                          
            bool operator!=(const standart_matrix<T>& other) const;      

Ругается на строчку №27 так:
Цитата

/home/jackyf/Work/Programming/linux/yfLibrary/workcopy-linux/yf/math/standart_matrix.hpp: In constructor ‘yf::math::standart_matrix<T>::standart_matrix(const T (&)[rows][columns]) [with long unsigned int rows = 2ul, long unsigned int columns = 3ul, T = int]’:
test.cpp:111:   instantiated from here
/home/jackyf/Work/Programming/linux/yfLibrary/workcopy-linux/yf/math/standart_matrix.hpp:67: error: no matching function for call to ‘yf::math::standart_matrix<int>::_ctor(<unresolved overloaded function type>, <unresolved overloaded function type>)’
/home/jackyf/Work/Programming/linux/yfLibrary/workcopy-linux/yf/math/standart_matrix.hpp:145: note: candidates are: void yf::math::standart_matrix<T>::_ctor(size_t, size_t) [with T = int]
/home/jackyf/Work/Programming/linux/yfLibrary/workcopy-linux/yf/math/standart_matrix.hpp:156: note:                 void yf::math::standart_matrix<T>::_ctor(const yf::math::standart_matrix<T>&) [with T = int]

Я же в функции ему передаю два size_t...  smile. Ну и денёк...

Автор: archimed7592 30.11.2007, 00:20
JackYF, йа колдун:
Код

archimed7592@PC ~/testlabs/g++
$ cat ./main.cpp
#include <iostream>
template<typename T>
class Matrix
{
public:
        template<int m, int n>
        Matrix(const T (&values)[m][n]);
};

template<typename T>
template<int m, int n>

Matrix<T>::Matrix(const T (&values)[m][n])
{
        std::cout << m << "," << n << std::endl;
        for (int i = 0; i < m; ++i)
        {
                for (int j = 0; j < n; ++j)
                        std::cout << values[i][j] << " ";
                std::cout << std::endl;
        }
}

int main()
{
        int x[2][3] = { {1, 2, 3}, {4, 5, 6} };
        Matrix<int> t(x);
        return 0;
}

archimed7592@PC ~/testlabs/g++
$ g++ -v
Reading specs from E:/prg/devel/msys/mingw/bin/../lib/gcc/mingw32/3.4.2/specs
Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --host=
mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --enable
-languages=c,c++,f77,ada,objc,java --disable-win32-registry --disable-shared --e
nable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-x --enable-ja
va-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-synchroniz
ation --enable-libstdcxx-debug
Thread model: win32
gcc version 3.4.2 (mingw-special)

archimed7592@PC ~/testlabs/g++
$ g++ ./main.cpp

archimed7592@PC ~/testlabs/g++
$

Автор: JackYF 30.11.2007, 00:24
Поломали они, что ли, это со времён 3-й мажорной версии?... тьху...

Автор: archimed7592 30.11.2007, 00:24
Тебе "<unresolved overloaded function type>" ни о чём не говорит? smile 

Автор: JackYF 30.11.2007, 00:25
Цитата(archimed7592 @  30.11.2007,  00:24 Найти цитируемый пост)
Тебе "<unresolved overloaded function type>" ни о чём не говорит? 

не-а. Я делаю _ctor(rows, columns), где rows типа size_t, columns типа size_t.

void _ctor(size_t, size_t); - функция есть.

Автор: archimed7592 30.11.2007, 00:28
Дай полный код, который по идее должен быть компилябельным.

Автор: bsa 30.11.2007, 00:34
попробуй для начала еще size_t в template заменить на unsigned long.

Автор: JackYF 30.11.2007, 00:41
Сложно... просто у меня исходники друг на друга завязаны, типа библиотека. Отвязывать один исходник от библиотеки - гиблая задача.
В общем, выкладываю весь tar.gz "библиотеки".

Исходник теста:

Код

#include <yf/math/standart_matrix.hpp>
int main()
{
        int x[2][3] = { {1, 2, 3}, {4, 5, 6} };
        yf::math::standart_matrix<int> t(x);
        return 0;
}


Путь к библиотеке распакованной только надо будет прописать. Собирать по идее не потребуется. Но если что - там lib/configure, lib/Makefile...
Пропиши этому чуду только -DYF_CODE_32... при сборке... и [WINDOWS|LINUX]...
Да. надо бы привести это к виду нормальному...

Спать... спать...

Добавлено @ 00:42
И почему это я не могу аттачить tar.gz...

Добавлено через 3 минуты и 10 секунд
Цитата(bsa @  30.11.2007,  00:34 Найти цитируемый пост)
попробуй для начала еще size_t в template заменить на unsigned long.

Попробовал. К сожалению, ноль эффекта.

Добавлено через 6 минут и 51 секунду
Ушёл спать... всем большое спасибо за участие. Авось на свежую голову что-то надумается, завтра продолжу.

Автор: archimed7592 30.11.2007, 01:01
JackYF, шаман хренов smile. Я же спросил: не смущает? Вот это что, уже не ф-ции:
Код

   size_t rows() const;
   size_t columns() const;
??

С переименованными параметрами собирается на ура smile.

Автор: JackYF 30.11.2007, 15:17
Чертить многополосные флагштоки!  smile  smile !!!
М-да-а... smile вот это я протупил... smile утро вечера мудренее smile

Цитата(archimed7592 @  30.11.2007,  01:01 Найти цитируемый пост)
С переименованными параметрами собирается на ура

ты таки собирал моё чудо? smile

Автор: archimed7592 30.11.2007, 17:17
Цитата(JackYF @  30.11.2007,  15:17 Найти цитируемый пост)
ты таки собирал моё чудо? smile 

угу - g++ ./main.cpp smile

Правда, пришлось немного пофиксить твои "кроссплатформенные" workaround'ы smile.

Автор: JackYF 30.11.2007, 20:11
Цитата(archimed7592 @  30.11.2007,  17:17 Найти цитируемый пост)
Правда, пришлось немного пофиксить твои "кроссплатформенные" workaround'ы

Не подскажешь, которые? smile

Автор: archimed7592 30.11.2007, 20:13
Точно помню, что ругалось на 0xFFFFFFFFFFFFFFFF(max uint 64), а чего ещё, ес честно не помню - спать хотелось и нажимал ctrl+y на автомате smile.

Автор: JackYF 30.11.2007, 21:59
Цитата(archimed7592 @  30.11.2007,  20:13 Найти цитируемый пост)
Точно помню, что ругалось на 0xFFFFFFFFFFFFFFFF(max uint 64)

учтём.

Цитата(archimed7592 @  30.11.2007,  20:13 Найти цитируемый пост)
спать хотелось и нажимал ctrl+y на автомате

ага, тоже в mcedit'е работаешь? smile

Добавлено через 23 секунды
Кстати, проблема-то решилась, наконец можно тему пометить как решённую.

Автор: archimed7592 30.11.2007, 22:16
Цитата(JackYF @  30.11.2007,  21:59 Найти цитируемый пост)
ага, тоже в mcedit'е работаешь? smile

Вообще, работаю в EmEditor'е(кстати советую, как тупой редактор с примитивной подсветкой), а твоё правилось в FAR'е smile.

Добавлено через 57 секунд
Всмысле редактор умный, но как IDE не катит smile. Зато работает шустро smile.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)