Является ли Собственная библиотека, модифицирующая синтаксис C ++ - PullRequest
0 голосов
/ 11 декабря 2019

Я недавно использовал Eigen, и хотя все имеет смысл, и меня немного смущает то, как библиотека сходит со странного синтаксиса, который она использует.

Например, при определении матрицы, вы должны сделать:

MatrixXd m(2,2); //defines a 3 x 4 matrix
m(0, 0) = 1;
m(0, 1) = 2;
m(1, 0) = 3;
m(1, 1) = 4;

или вы можете сделать что-то вроде:

Matrix3f m;
m << 1, 2, 3,
     4, 5, 6,
     7, 8, 9;
std::cout << m;

Хотя эти команды имеют смысл для меня концептуально, мне интересно, как они имеют смыслкомпилятор. Я думал, что << использовался для сдвига битов и что скобочная нотация использовалась для ввода функций параметров или чего-то еще, а не для разбора матричной структуры, такой как массив. </p>

Я не работал с C ++ длядостаточно долго, чтобы понять весь этот синтаксис, но мне было интересно, определили ли авторы Eigen собственный синтаксис или что-то в этом роде.

Ответы [ 2 ]

1 голос
/ 12 декабря 2019

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

В первом блоке кода строка MatrixXd m(2,2); - это , создающая объект , так как это объявление, и у нас есть тип MatrixXd. Следовательно, синтаксис m(i, j) должен быть вызовом конструктора, получающего два параметра (он также может быть конструктором, получающим больше параметров, если другие параметры имеют значения по умолчанию).

Другие строки в первом блоке кода не вызывают конструктор, и поэтому синтаксис m(i, j) означает вызов реализации operator()(i, j). Технически, что-то похожее на operator()(int i, int j). Таким образом, первый блок кода нуждается только в одной перегрузке оператора, и его часто используют один человек.

Второй блок кода мне кажется больше волшебным. Часть m << Number означает, что тип m, который является Matrix3f, имеет перегрузку для operator<<. Тогда я думаю, что тип того, что operator<< возвращает 1 , должен иметь реализацию оператора запятой, чтобы разрешить часть 1, 2, 3, .... Оператор запятой используется редко, и это самый непонятный оператор для перегрузки IMHO. Таким образом, второй блок кода требует двух перегрузок операторов, и одна из них является более неясной. Да, это волшебство.


1 Это может быть ссылка на m и, следовательно, Matrix3f или даже совершенно другой тип, созданный авторами Eigen дляразрешить этот хороший синтаксис для инициализации матрицы.

1 голос
/ 11 декабря 2019

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

#include <array>
#include <iostream>

struct my_matrix {
    std::array< std::array< int,10>,10> data;
    int& operator()(size_t i,size_t j) { return data[i][j]; }
    const int& operator()(size_t i,size_t j) const { return data[i][j]; }
};


int main (){
    my_matrix x;
    x(1,1) = 42;
    std::cout << x(1,1);
}

Перегрузка operator() довольно гибкая, так как позволяет использовать несколько параметров. Возврат ссылки на элемент data позволяет пользователю изменять элементы неконстантного my_matrix. Чтобы также разрешить доступ к элементам const my_matrix (без их изменения), существует также перегрузка const оператора. Подобно перегрузке operator(), << также является оператором, который может быть перегружен для выполнения разных задач. Подробнее о перегрузке операторов см. здесь и здесь .

...