[Eigen中文文档] 断言

简介: 宏 eigen_assert默认定义为 eigen_plain_assert。我们使用 eigen_plain_assert而不是 assert来解决 GCC <= 4.3 的已知错误。基本上,eigen_plain_assert就是断言。

文档总目录

英文原文(Assertions)

断言

eigen_assert默认定义为 eigen_plain_assert。我们使用 eigen_plain_assert而不是 assert来解决 GCC <= 4.3 的已知错误。基本上,eigen_plain_assert就是断言。

重新定义断言

eigen_asserteigen_plain_assert两者都定义在Macros.h文件中。定义eigen_assert间接地提供了更改其行为的机会。如果您想执行其他操作(例如抛出异常),则可以重新定义此宏,并使用eigen_plain_assert返回其默认行为。以下代码告诉Eigen抛出一个std::runtime_error异常:

#include <stdexcept>
#undef eigen_assert
#define eigen_assert(x) \
  if (!(x)) { throw (std::runtime_error("Put your message here")); }

禁用断言

断言会消耗运行时间并且可以关闭。您可以通过在包含 Eigen 标头之前定义 EIGEN_NO_DEBUG来抑制 eigen_assertEIGEN_NO_DEBUG默认情况下未定义,除非定义了 NDEBUG

静态断言

静态断言直到 C++11 才标准化。然而,在 Eigen 库中,有很多条件可以而且应该在编译时检测到。例如,我们使用静态断言来防止下面的代码编译。

Matrix3d()  + Matrix4d();   // adding matrices of different sizes
Matrix4cd() * Vector3cd();  // invalid product known at compile time

静态断言在 StaticAssert.h 中定义。如果有原生的 static_assert,我们就使用它。否则,我们实现了一个断言宏,可以显示有限范围的消息。

可以轻松地提出没有消息的静态断言,例如:

#define STATIC_ASSERT(x) \
  switch(0) { case 0: case x:; }

然而,上面的例子显然无法说明断言失败的原因。因此,我们在命名空间 Eigen::internal 中定义一个结构体来处理可用的消息。

template<bool condition>
struct static_assertion {
   };

template<>
struct static_assertion<true>
{
   
  enum {
   
    YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX,
    YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES,
    // see StaticAssert.h for all enums.
  };
};

然后,我们定义EIGEN_STATIC_ASSERT(CONDITION,MSG)以访问Eigen::internal::static_assertion<bool(CONDITION)>::MSG。如果条件计算为false,则编译器会显示许多消息,说明在static_assert<false>中不存在MSG。尽管如此,这不是我们感兴趣的。正如您所看到的,static_assert<true>的所有成员都是使用ALL_CAPS_AND_THEY_ARE_SHOUTING

警告:

使用此宏时,MSG 应该是 static_assertion<true> 的成员,否则静态断言总是失败。目前,它只能在函数范围内使用。

派生静态断言

还有其他从 EIGEN_STATIC_ASSERT 派生的宏来增强可读性。他们的名字是不言自明的。

  • EIGEN_STATIC_ASSERT_FIXED_SIZE(TYPE) 如果 TYPE 是固定大小则通过。
  • EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(TYPE) 如果 TYPE 是动态大小则通过。
  • EIGEN_STATIC_ASSERT_LVALUE(Derived) 如果 Derived 是只读的,则失败。
  • EIGEN_STATIC_ASSERT_ARRAYXPR(Derived) 如果 Derived 是数组表达式,则通过。
  • EIGEN_STATIC_ASSERT_SAME_XPR_KIND(Derived1, Derived2) 如果两个表达式是数组和矩阵,则失败。

由于 Eigen 同时处理固定大小和动态大小表达式,因此某些条件无法在编译时明确确定。我们将它们分为严格断言和宽容断言。

严格断言

如果条件不满足,这些断言就会失败。例如,MatrixXd可能不是向量,因此它会失败 EIGEN_STATIC_ASSERT_VECTOR_ONLY

  • EIGEN_STATIC_ASSERT_VECTOR_ONLY(TYPE) 如果 TYPE 必须是向量类型,则通过。
  • EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(TYPE, SIZE) 如果 TYPE 必须是给定大小的向量,则通过。
  • EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(TYPE, ROWS, COLS) 如果 TYPE 必须是具有给定行和列的矩阵,则通过。
宽容断言

如果无法满足条件,这些断言就会失败。例如,MatrixXdMatrix4d可能具有相同的大小,因此它们传递 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE

  • EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(TYPE0,TYPE1) 如果两个向量表达式类型必须具有不同的大小,则失败。
  • EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(TYPE0,TYPE1) 如果两个矩阵表达式类型必须具有不同的大小,则失败。
  • EIGEN_STATIC_ASSERT_SIZE_1x1(TYPE) 如果 TYPE 不能是 1x1 表达式,则失败。

有关它们抛出的消息等详细信息,请参阅 StaticAssert.h

禁用静态断言

如果定义了 EIGEN_NO_STATIC_ASSERT,静态断言将变成 eigen_assert,工作方式如下:

#define EIGEN_STATIC_ASSERT(CONDITION,MSG) eigen_assert((CONDITION) && #MSG);

这节省了编译时间,但消耗了更多运行时间。默认情况下,EIGEN_NO_STATIC_ASSERT 未定义。

相关文章
|
8月前
|
存储 编译器 C语言
[Eigen中文文档] 对未对齐数组断言的解释
本文将解释程序因断言失败而终止的问题。
74 0
|
8月前
|
存储 编译器
[Eigen中文文档] 深入了解 Eigen - 类层次结构
本页面介绍了Eigen类层次结构中 Core 类的设计及其相互关系。一般用户可能不需要关注这些细节,但对于高级用户和Eigen开发人员可能会有用。
131 0
|
8月前
|
存储 安全 编译器
[Eigen中文文档] 常见的陷阱
本文将介绍一些Eigen常见的陷阱
97 0
|
8月前
|
存储 C语言 C++
|
8月前
|
存储 编译器
|
8月前
|
存储 缓存
[Eigen中文文档] 深入了解 Eigen - 惰性求值与混叠(Aliasing)
Eigen具有智能的编译时机制,可以实现惰性求值并在适当的情况下删除临时变量。它会自动处理大多数情况下的混叠问题,例如矩阵乘积。自动行为可以通过使用MatrixBase::eval()和MatrixBase::noalias()方法手动覆盖。
90 0
|
8月前
[Eigen中文文档] 编写以特征类型为参数的函数(一)
Eigen使用表达式模板的方式导致每个表达式的类型可能都不同。如果将这样的表达式传递给一个需要Matrix类型参数的函数,则表达式将隐式地被评估为一个临时Matrix,然后再传递给函数。这意味着失去了表达式模板的好处。
80 0
|
8月前
|
安全
[Eigen中文文档] 混叠
在 Eigen 中,混叠是指相同的矩阵(或数组或向量)出现在赋值操作符的左边和右边。如下表达式,mat = 2*mat 或者 mat = mat.transpose()。第一个表达式是没有问题的,但是第二个表达式,会出现不可预料的结果。这一节会解释什么是混叠,以及它的危害与处理方法。
55 0
|
8月前
|
测试技术 API C++
[Eigen中文文档] 扩展/自定义Eigen(一)
在本节中,将介绍如何向MatrixBase添加自定义方法。由于所有表达式和矩阵类型都继承自MatrixBase,因此将方法添加到MatrixBase会立即使其对所有表达式可用!一个典型的用例是,使Eigen与另一个API兼容。
111 0
|
8月前
|
存储 索引
[Eigen中文文档] 扩展/自定义Eigen(三)
本页面针对非常高级的用户,他们不害怕处理一些Eigen的内部细节。在大多数情况下,可以通过使用自定义一元或二元函数避免使用自定义表达式,而极其复杂的矩阵操作可以通过零元函数(nullary-expressions)来实现,如前一页所述。 本页面通过示例介绍了如何在Eigen中实现新的轻量级表达式类型。它由三个部分组成:表达式类型本身、包含有关表达式编译时信息的特性类和评估器类,用于将表达式评估为矩阵。
67 1