Eigen库是在修改C++语法吗
Is the Eigen Library Modifying C++ Syntax
我最近一直在使用 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;
虽然这些命令在概念上对我来说很有意义,但我很好奇它们对编译器有何意义。我以为<<是用来做位移的,括号是用来输入参数函数什么的,不是用来解析数组之类的矩阵结构的
我使用 C++ 的时间还不够长,无法理解所有这些语法,但我想知道 Eigen 的作者是否以某种方式定义了自定义语法或其他东西。
我不知道 Eigen,我认为你应该看看这些运算符是如何实现的。但是,一个小玩具示例可能有助于了解发生了什么。
#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()
类似,<<
也是一个可以重载以执行不同操作的运算符。有关运算符重载的更多信息,请参阅 here and here.
在这两个代码块中都有一些运算符重载。
在第一个代码块中,行 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<<
returns1 的类型必须有逗号运算符的实现以允许 1, 2, 3, ...
部分。逗号运算符很少使用,它是重载恕我直言的最晦涩的运算符。总之,第二个代码块需要两个运算符重载,其中一个比较晦涩。是的,这很神奇。
1 它可能是对 m
的引用,因此是 Matrix3f
或者它甚至可能是由 Eigen 作者创建的完全不同的类型以允许这种初始化矩阵的好语法。
我最近一直在使用 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;
虽然这些命令在概念上对我来说很有意义,但我很好奇它们对编译器有何意义。我以为<<是用来做位移的,括号是用来输入参数函数什么的,不是用来解析数组之类的矩阵结构的
我使用 C++ 的时间还不够长,无法理解所有这些语法,但我想知道 Eigen 的作者是否以某种方式定义了自定义语法或其他东西。
我不知道 Eigen,我认为你应该看看这些运算符是如何实现的。但是,一个小玩具示例可能有助于了解发生了什么。
#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()
类似,<<
也是一个可以重载以执行不同操作的运算符。有关运算符重载的更多信息,请参阅 here and here.
在这两个代码块中都有一些运算符重载。
在第一个代码块中,行 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<<
returns1 的类型必须有逗号运算符的实现以允许 1, 2, 3, ...
部分。逗号运算符很少使用,它是重载恕我直言的最晦涩的运算符。总之,第二个代码块需要两个运算符重载,其中一个比较晦涩。是的,这很神奇。
1 它可能是对 m
的引用,因此是 Matrix3f
或者它甚至可能是由 Eigen 作者创建的完全不同的类型以允许这种初始化矩阵的好语法。