问题标签 [expression-templates]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
0 回答
130 浏览

c++ - C++:表达式模板中循环的性能

我在类似矢量的类中使用表达式模板进行转换,例如移动平均线。在这里,与标准算术运算不同,operator[](size_t i)不会对 element 进行单个访问i,而是需要评估整个循环,例如对于向量的移动平均值v

(这不是真正的功能,因为必须关心非负索引,但现在这无关紧要)。

在使用这种移动平均线结构时,我担心代码会变得相当低效,尤其是在采用双重或三重移动平均线的情况下。然后获得嵌套循环,因此获得周期大小的二次或三次缩放。

我的问题是,编译器是否如此聪明地以某种方式优化这些冗余循环?还是不是这种情况,必须手动处理中间存储(我猜是这样)?如何在下面的示例代码中合理地做到这一点?


示例代码,改编自Wikipedia,使用 Visual Studio 2013 编译:

CRTP 基类和实际向量:

移动平均线类:

现在我上面提到的恐惧出现在这样的表达中,

我想这需要20^3对单个 ... 进行评估operator[]


编辑:一个明显的解决方案是存储结果。移动std::vector<double> data到基类,然后将移动平均类更改为(未经测试)

然后可以在函数中选择存储结果:

这可以扩展为仅将存储应用于多个应用程序等。

0 投票
1 回答
361 浏览

c++ - 构造具有函数属性的 qi::rule

我正在尝试创建一个规则,该规则返回function<char(char const *)>通过对 Phoenix 表达式进行柯里化构建的规则。例如,

应该xxx是什么让解析字符串"5"应该给我一个函数,给我输入的第五个字符?我已经尝试过lambda(_a = arg1)[arg1[_a]](_1)可能有用的方法,但我无法找到神奇的公式。

换句话说,我希望属性对arg2[arg1]解析的 int 的值进行curry

非常感谢任何建议。请注意,我使用的是 VC2008,因此 C++11 lambda 不可用。

麦克风

0 投票
3 回答
87 浏览

c++ - 模板类中的模板函数

我正在构建一个使用表达式模板的库,我在类中大量使用模板化函数。我所有的代码都在运行,最近我决定将主类模板化以允许在不同类型的数据上使用它。但是,我不能再专门化我的功能。我该如何解决这个问题?我附上了一个显示问题的小测试程序。

我以前的Animal课程没有模板化,然后这段代码可以正常工作。

0 投票
1 回答
172 浏览

c++ - 分析表达式模板

我正在尝试分析类似于 David Vandevoorde 的“C++ 模板”一书中的表达式模板。下面是我的理论分析,这可能是错误的,因为测试显示了意想不到的结果。假设测试是关于:

其中 A、B、C、R 是在堆上分配的数组。数组的大小为 2。因此将执行以下操作:

大约有 12 条指令(每条指令 6 条)。

现在,如果启用了表达式模板(显示在最底部),在编译器时进行类型推导后,将在运行时处理以下内容,然后执行与上述相同的评估:

因此,在评估之前总共有 2+3=5 条指令,约占总指令的 5/(5+12)=30%。所以我应该能够看到这种开销,尤其是当向量大小很小的时候。

但结果表明,两者的成本几乎相同。我将测试迭代 1E+09 次。当然,两者的汇编代码是相同的。但是我找不到这个“构造”部分需要花费任何时间或说明的部分。

我没有良好的CS背景,所以这个问题可能很愚蠢。但是这几天我一直在摸不着头脑。因此,任何帮助都是值得的!

--- 我的表情模板 ---

其中,traits 什么都不做,只是决定是否应该采用对象的引用值。例如,值是为整数复制的,但引用是为数组获取的。

0 投票
3 回答
94 浏览

c++ - 令人困惑的表达式模板 Segfault 与 O3

在我的 gcc-4.8.1 上,我使用两个命令编译了以下程序:

第一个可执行文件具有预期的输出,但第二个可执行文件有段错误。问题是很难调试,因为-O3与代码混淆太多以至于-g调试信息无法保留意义,因此gdb在翻译源代码中发生的事情时遇到了麻烦。所以,我开始插入打印语句。正如我所料,打印语句改变了结果。使用调试打印,它工作得很好!

这是我的表达式模板源:

很久-O3没有给我一个不正确/不可靠的二进制文件了。我首先假设我在代码中做错了什么,但还不足以-O0显示它。有人知道我做错了什么吗?

0 投票
1 回答
319 浏览

c++ - 使用使用 auto 关键字创建的类型的表达式模板中的分段错误

我正在为计算内核构建带有表达式模板的代码。我的问题很简短:为什么 GNU G++ 在包含+=以下示例的行中给出段错误(4.9.1,使用 -O3 编译):

但不是当我键入等效代码时:

Clang 和 Intel 都可以正常工作。

我在下面添加了整个代码。抱歉,这是我可以创建的最短示例:

0 投票
1 回答
183 浏览

c++ - 表达式模板:错误 C2784 '无法推断模板参数'

我正在研究一个使用表达式模板的向量类。我有以下(减少的)代码。在“Vector.h”中:

然后,在“main.cpp”中:

现在,如果我注释掉normalizeclass中的成员Expression,代码就会编译,一切都按我的预期工作,包括哪些版本lengthnormalize被调用。但是,如果我不normalize注释该成员,则会收到以下编译器错误:

我希望能够将 normalize 调用为作用于 aVector或的独立函数,Expression或者作为Expression类似于它完成方式的继承成员调用length,它可以正确编译和工作。的独立版本normalize也可以正常工作。normalize我对班级成员的定义有什么问题?

谢谢!

0 投票
0 回答
722 浏览

c++ - 将 Eigen 与表达式模板参数一起使用会减慢编译时间

我正在编写一个 C++ 库,在其中我使用在 Eigen3 中作为参数表达式模板的函数。基本上我的函数的定义类似于

输入参数乍一看有点奇怪,但它真正的作用是它允许使用表达式模板。例如,我可以使用类似的功能

上述参数的类型是一些在这里拼写非常长的模板类型(表达式模板),而不是普通矩阵。这样的表达式模板允许速度优化等,所以我真的需要使用它们。

现在是我的问题

我有很多这样的函数,每当我用不同的表达式实例化它们时,编译器都会在编译时生成一个实例化,因此编译时间会变长一些。在我的情况下,它仍然很好,在 i5 8GB RAM 上大约需要 30 秒,但是我非常想减少编译时间。有什么方法或技巧可以用来以某种方式减少编译时间但仍然能够使用表达式模板?

0 投票
1 回答
1649 浏览

c++ - 如何围绕表达式模板编写第三方库包装类

我们正在尝试在我的研究小组中实现一个新的 C++ 代码来执行大型数值模拟(有限元、有限差分方法、拓扑优化等)。该软件将被学术界和工业界的人们使用。

对于软件的密集线性代数部分,我们想使用 Eigen 或 Armadillo。我们希望围绕这些包构建一个包装器有两个原因: 1. 向用户公开我们自己的 API 而不是第三方 API;2.以防我们将来需要切换库。我知道原因 2 是一种非常昂贵的保险形式,但是我们在使用之前的模拟软件时遇到了这种情况。

我遇到的有关包装第三方库的信息来自以下来源:

我的问题与构建这个包装类的最佳方法有关。理想情况下,薄层包装将是最好的,因为:

或其与特征向量的等价物。

然后,我的类将调用第三方库类:

我认为(并且我想对此进行确认)这个薄层的问题是我失去了从这些库在引擎盖下实现的表达式模板获得的速度。例如,在犰狳中,以下操作:

变成这样:

由于它们实现了表达式模板,因此无需创建任何临时对象。同样的情况也适用于本征。

据我所知,我失去表达式模板功能的原因是,虽然犰狳或 Eigen 不会创建自己的临时对象,但我的类 my_vec 会。避免这种情况的唯一方法是在其表达式模板周围构建一个薄层包装器。但是,在这一点上,这似乎违反了 YAGNI 原则。

这个相关的问题在这里:

建议使用类似的东西:

可以改用这样的东西吗?

或者使用一些运算符重载来向用户隐藏 data() ?如果我们不想直接使用这些库,还有哪些其他选择?使用宏?如果我们决定使用 C++11,使用别名?

或者构建这个包装类最方便的方法是什么?

0 投票
1 回答
106 浏览

c++ - 如何在声明变量时评估表达式(在表达式模板中)

我正在尝试探索 C++ 中的表达式模板。我正在尝试为 3D 矢量(基本上是大小为 3 的矢量)创建一个类,用于存储坐标、空间矢量、力等,它们基本上具有三个组件。

到目前为止,我只实现了类来执行两个向量的求和。如果我编写代码,代码可以正常工作vector3d z; z = x + y;。即,如果我首先声明 z 变量然后执行加法。但是,当我尝试用vector3d z = x + y;一​​句话来写时,我得到了错误。我明白了error: conversion from 'const ExprSum<vector3d, vector3d>' to non-scalar type 'vector3d' requested vector3d z_new = x + y ;

我应该如何实现才能=在变量声明期间使用?

以下是我的完整代码: